Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/flickerable.coffee
+++ test/flickerable.coffee
@@ -15,6 +15,8 @@
   equals player.I.alpha, 0.2

   4.times ->
+    player.update()

+  equ

 module()


test: test for memory leaks

test: test for memory leaks

--- test/reservation.coffee
+++ test/reservation.coffee
@@ -74,7 +74,16 @@
       return cb "no_reservations" unless state
       return cb null, 'patience_is_bitter_but_fruit_is_sweet'

-describe "redis-reservation", ->
+describe 'ReserveResource', ->
+  it "doesn't leak memory", ->
+    # Essentially just asserting that we can instantiate 10 milliion ReserveResources without
+    # running out of memory, so not quite the same as actuall testing for memory leaks, but good
+    # enough.
+    for i in [0...10000000]
+      resource = new ReserveResource 'some worker', process.env.REDIS_HOST, process.env.REDIS_PORT
+      resource._init_redis()
+
+describe 'redis-reservation', ->

   before (done) ->
     @redis = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST)


move check for child into nodetype class

--- src/mmd.coffee
+++ src/mmd.coffee
@@ -13,8 +13,12 @@
   addValue: (val) ->
     @values.push val unless @values.indexOf val

-  addChild: (name) ->
-    @children[name] = new NodeType name
+  getChild: (name) ->
+    this_type = @children[name]
+    if this_type?
+      this_type.plural on
+    else
+      @children[name] = new NodeType name

 analyze = (et, continuing) ->
   root = new NodeType 'root'
@@ -24,12 +28,7 @@

 analyzeNode = (parent_type, node) ->
   children = node.getchildren()
-  this_type = parent_type.children[node.tag]
-
-  if this_type?
-    this_type.plural on
-  else
-    this_type = parent_type.addChild node.tag
+  this_type = parent_type.getChild node.tag

   if children.length is 0
     this_type.addValue node.text


fix typo

fix typo

--- src/ref.coffee
+++ src/ref.coffee
@@ -31,7 +31,7 @@
     @

   # Removes reference
-  destroy(removeEvents = false) ->
+  destroy: (removeEvents = false) ->
     child.destroy(removeEvents) for id, child of @_children
     delete @_cache
     delete @_children


fixed close event

fixed close event

--- src/xml.coffee
+++ src/xml.coffee
@@ -154,7 +154,6 @@
     end: () =>
         if not @closed or @closed is 'pending'
             if @pending.length
-                @emit 'close', this if @closed isnt 'pending'
                 @closed = 'pending'
             else
                 if @isempty
@@ -165,7 +164,9 @@
                     @closed = yes
                 @emit 'data', prettify this, data

-            @emit 'end' unless @closed is 'pending'
+            unless @closed is 'pending'
+                @emit 'close', this
+                @emit 'end'
         else if @closed is 'removed'
             @emit 'end'
         else


Fix typo

Fix typo

--- snippets/tests.cson
+++ snippets/tests.cson
@@ -1,6 +1,6 @@
 '.source.php':
     'Laravel Test Case':
-        'prefix': 'testcase2'
+        'prefix': 'testcase'
         'body': """
             use Illuminate\\\\Foundation\\\\Testing\\\\WithoutMiddleware;
             use Illuminate\\\\Foundation\\\\Testing\\\\DatabaseMigrations;


change test timeout

change test timeout

--- tests/functional.coffee
+++ tests/functional.coffee
@@ -225,7 +225,7 @@
                     # file should exist
                     fs.existsSync(filePath).should.be.ok
                     done()
-                , 5000
+                , 7000

     it "Rename a file remotely", (done) ->
         @timeout 15000
@@ -240,10 +240,10 @@
                     # file should exist
                     fs.existsSync(newPath).should.be.ok
                     done()
-                , 6000
+                , 7000

     it "Create a folder remotely", (done) ->
-        @timeout 20000
+        @timeout 15000
         folderName = 'remote-folder'
         folderPath = "#{syncPath}/#{folderName}"
         filesHelpers.createFolder folderName, ->
@@ -254,10 +254,10 @@
                     # folder should exist
                     fs.existsSync(folderPath).should.be.ok
                     done()
-                , 15000
+                , 7000

     it "Move a file remotely into a subfolder", (done) ->
-        @timeout 30000
+        @timeout 15000
         fileName = 'chat-mignon-renamed.jpg'
         folderName = 'remote-folder'
         newPath = "#{syncPath}/#{folderName}/#{fileName}"
@@ -274,7 +274,7 @@
                         # file should exist at new path
                         fs.existsSync(newPath).should.be.ok
                         done()
-                    , 25000
+                    , 7000

     it "Move a file remotely from a subfolder", (done) ->
         @timeout 15000
@@ -295,10 +295,10 @@
                             # file should exist at new path
                             fs.existsSync(newPath).should.be.ok
                             done()
-                        , 6000
+                        , 7000

     it "Delete a file remotely", (done) ->
-        @timeout 20000
+        @timeout 15000

         fileName = 'chat-mignon-renamed.jpg'
         filePath = "#{syncPath}/#{fileName}"
@@ -313,7 +313,7 @@
                     # file should exist at new path
                     fs.existsSync(filePath).should.not.be.ok
                     done()
-                , 15000
+                , 7000

     ###it "Rename a folder remotely", (done) ->
         @timeout 15000


Added debug code

Added debug code

--- tests/integrated.coffee
+++ tests/integrated.coffee
@@ -88,6 +88,7 @@
           path.join("./tests/data/multiple", file)
         ).then(
           (data) ->
+            console.log data.toString "utf8"
             resultPath = path.join("./tests/results/multiple", file)
             if not right[resultPath]
               right[resultPath] = {}
@@ -100,6 +101,7 @@
           path.join("./tests/data/multiple", file + ".map")
         ).then(
           (data) ->
+            console.log data.toString "utf8"
             resultPath = path.join("./tests/results/multiple", file)
             if not right[resultPath]
               right[resultPath] = {}


Reload paths when any dependent config value changes

Previously only fuzzy-finder.ignoredNames was watched but
core.ignoredNames and core.excludeVcsIgnoredPath are also used by
the path loader so any changes to those two config settings should
trigger a reload.

--- lib/project-view.coffee
+++ lib/project-view.coffee
@@ -23,12 +23,21 @@
         # so let it complete but reload the paths on the next populate call.
         @reloadAfterFirstLoad = true

-    @subscribe atom.config.observe 'fuzzy-finder.ignoredNames', callNow: false, =>
-      @reloadPaths = true
+    @subscribeToConfig()

     @subscribe atom.project, 'path-changed', =>
       @reloadPaths = true
       @paths = null
+
+  subscribeToConfig: ->
+    @subscribe atom.config.observe 'fuzzy-finder.ignoredNames', callNow: false, =>
+      @reloadPaths = true
+
+    @subscribe atom.config.observe 'core.ignoredNames', callNow: false, =>
+      @reloadPaths = true
+
+    @subscribe atom.config.observe 'core.excludeVcsIgnoredPaths', callNow: false, =>
+      @reloadPaths = true

   toggle: ->
     if @hasParent()


Remove unused requires

Remove unused requires

--- src/app/config.coffee
+++ src/app/config.coffee
@@ -1,10 +1,6 @@
 fs = require 'fs'
 _ = require 'underscore'
 EventEmitter = require 'event-emitter'
-{$$} = require 'space-pen'
-jQuery = require 'jquery'
-Specificity = require 'specificity'
-Theme = require 'theme'

 configDirPath = fs.absolute("~/.atom")
 configJsonPath = fs.join(configDirPath, "config.json")


Fix isReversed option name

Fix isReversed option name

--- src/app/editor.coffee
+++ src/app/editor.coffee
@@ -670,8 +670,7 @@
     $(document).one "mouseup.editor-#{@id}", =>
       clearInterval(interval)
       $(document).off 'mousemove', moveHandler
-      reverse = @activeEditSession.getLastSelection().isReversed()
-      @activeEditSession.mergeIntersectingSelections({reverse})
+      @activeEditSession.mergeIntersectingSelections(isReversed: @activeEditSession.getLastSelection().isReversed())
       @activeEditSession.finalizeSelections()
       @syncCursorAnimations()


add scrollToTab

add scrollToTab

--- lib/tab-bar-view.coffee
+++ lib/tab-bar-view.coffee
@@ -115,6 +115,8 @@
       @insertBefore(tab, followingTab)
     else
       @appendChild(tab)
+
+    @scrollToTab(tab)
     tab.updateTitle()
     @updateTabBarVisibility()

@@ -123,6 +125,15 @@
     tab.updateTitle() for tab in @getTabs()
     @updateTabBarVisibility()

+  scrollToTab: (tab) ->
+    tabRightEdge = tab.offsetLeft + tab.offsetWidth
+    tabBarRightEdge = this.scrollLeft + this.offsetWidth
+
+    if tabRightEdge > tabBarRightEdge
+      this.scrollLeft = tabRightEdge - this.offsetWidth
+    else if this.scrollLeft > tab.offsetLeft
+      this.scrollLeft = tab.offsetLeft
+
   updateTabBarVisibility: ->
     if not atom.config.get('tabs.alwaysShowTabBar') and not @shouldAllowDrag()
       @classList.add('hidden')
@@ -142,6 +153,7 @@
     if tabView? and not tabView.classList.contains('active')
       @querySelector('.tab.active')?.classList.remove('active')
       tabView.classList.add('active')
+      @scrollToTab(tabView)

   getActiveTab: ->
     @tabForItem(@pane.getActiveItem())


Add shift-z for redo, and make sure cursor is always correct

--- src/controller.coffee
+++ src/controller.coffee
@@ -665,7 +665,9 @@

 # Now we hook to ctrl-z to undo.
 hook 'keydown', 0, (event, state) ->
-  if event.which is Z_KEY and command_pressed(event)
+  if event.which is Z_KEY and event.shiftKey and command_pressed(event)
+    @redo()
+  else if event.which is Z_KEY and command_pressed(event)
     @undo()
   else if event.which is Y_KEY and command_pressed(event)
     @redo()
@@ -698,6 +700,7 @@
       @tree.perform(operation, 'backward', [@cursor]) unless operation is 'CAPTURE'

   @popUndo()
+  @correctCursor()
   @redrawMain()
   return

@@ -750,6 +753,7 @@
     @pushUndo operation

   @prepareNode node, null
+  @correctCursor()
   return operation

 Editor::spliceIn = (node, location) ->
@@ -766,12 +770,19 @@
   operation = null
   operation = @tree.insert location, node, [@cursor]
   @pushUndo operation
+  @correctCursor()
   return operation

 Editor::replace = (before, after, updates) ->
   operation = @tree.replace before, after, updates
   @pushUndo operation
+  @correctCursor()
   return operation
+
+Editor::correctCursor = ->
+  cursor = @tree.getFromLocation(@cursor)
+  unless @validCursorPosition cursor
+    @setCursor cursor

 Editor::prepareNode = (node, context) ->
   if node instanceof model.Container
@@ -2429,6 +2440,7 @@
     return

   @setCursor block.start, null, 'before'
+  @undoCapture()
   @spliceOut block
   @redrawMain()


Track showing and hiding layers

Track showing and hiding layers

--- site/index.coffee
+++ site/index.coffee
@@ -35,7 +35,10 @@
   events:
     "change .check": "toggleCheckbox"
   toggleCheckbox: (e) ->
-    @model.set shown: @$("input").is(":checked")
+    isChecked = @$("input").is ":checked"
+    @model.set shown: isChecked
+    event = if isChecked then "Showed Layer" else "Hid Layer"
+    mpq.track event, name: @model.get "name"
   render: ->
     $(@el).children().remove()
     checkbox = $("<input type='checkbox' class='check'>")


atom: update preferred line length

atom: update preferred line length

--- atom/config.cson
+++ atom/config.cson
@@ -28,7 +28,7 @@
     scrollSensitivity: 25
     fontFamily: "Monaco"
     fontSize: 12
-    preferredLineLength: 30
+    preferredLineLength: 80
   "autocomplete-python": {}
   whitespace:
     ignoreWhitespaceOnCurrentLine: false


:atom: Update config.cson for Atom

:atom: Update config.cson for Atom

--- atom/config.cson
+++ atom/config.cson
@@ -10,6 +10,10 @@
     "atom-ide-datatip":
       datatipDebounceDelay: 500
     use: {}
+  "atom-package-deps":
+    ignored: [
+      "prettier-atom"
+    ]
   "autocomplete-emojis":
     enableUnicodeEmojis: false
   "autocomplete-plus":
@@ -17,6 +21,8 @@
     minimumWordLength: 1
   "bracket-matcher":
     highlightMatchingLineNumber: true
+  "color-picker":
+    randomColor: false
   core:
     customFileTypes:
       "source.ruby": [
@@ -54,7 +60,6 @@
     lightLevelToSwitch: 5904360
   "prettier-atom":
     formatOnSaveOptions:
-      enabled: true
       excludedGlobs: [
         "*.md"
       ]


Update atom keymaps

Update atom keymaps

--- atom/keymap.cson
+++ atom/keymap.cson
@@ -4,9 +4,6 @@

 '.platform-win32, .platform-linux':
   'ctrl-Á': 'editor:toggle-line-comments'
-
-'atom-workspace':
-  'ctrl-n': 'find-and-replace:select-next'

 #
 # tree-view
@@ -18,8 +15,18 @@
 # vim-mode-plus
 #
 ## *-mode
+'body, atom-text-editor':
+  'ctrl-j': 'core:move-down'
+  'ctrl-k': 'core:move-up'
+  'ctrl-q': 'core:close'
+
+  # Tab navigation
+  'ctrl-h': 'pane:show-previous-item'
+  'ctrl-l': 'pane:show-next-item'
+
 'atom-text-editor.vim-mode-plus':
   'ctrl-c': 'core:copy'
+  'ctrl-n': 'find-and-replace:select-next'

 ## normal-mode, visual-mode
 'atom-text-editor.vim-mode-plus:not(.insert-mode)':
@@ -37,6 +44,25 @@

   'ctrl-f': 'find-and-replace:show'

+  # Subword motion
+  '-': 'vim-mode-plus:move-to-next-subword'
+  '_': 'vim-mode-plus:move-to-previous-subword'
+
+  # Surround
+  'S': 'vim-mode-plus:surround'
+  'S d': 'vim-mode-plus:delete-surround-any-pair'
+  'S D': 'vim-mode-plus:delete-surround-any-pair'
+  'S S d': 'vim-mode-plus:delete-surround'
+  'S S D': 'vim-mode-plus:delete-surround'
+  'S c': 'vim-mode-plus:change-surround-any-pair'
+  'S C': 'vim-mode-plus:change-surround-any-pair'
+  'S S c': 'vim-mode-plus:change-surround'
+  'S S C': 'vim-mode-plus:change-surround'
+
+  # Tab navigation
+  'g T': 'unset!'
+  'g t': 'unset!'
+
   # Pane navigation
   'space h': 'window:focus-pane-on-left'
   'space l': 'window:focus-pane-on-right'
@@ -50,18 +76,33 @@
   'space s j': 'pane:split-down-and-copy-active-item'

   # Move panes
-  'space s m h': 'move-panes:move-left'
-  'space s m l': 'move-panes:move-right'
-  'space s m k': 'move-panes:move-up'
-  'space s m j': 'move-panes:move-down'
+  'space s H': 'move-panes:move-left'
+  'space s L': 'move-panes:move-right'
+  'space s K': 'move-panes:move-up'
+  'space s J': 'move-panes:move-down'

-  ## PSCIDE
+## operator-pending, visual-mode
+'atom-text-editor.vim-mode-plus.operator-pending-mode, atom-text-editor.vim-mode-plus.visual-mode':
+  # Subword text object
+  'a -': 'vim-mode-plus:a-subword'
+  'i -': 'vim-mode-plus:inner-subword'
+
+## PSCIDE
+'atom-text-editor.vim-mode-plus[data-grammar~="purs"]:not(.insert-mode), atom-text-editor.vim-mode-plus[data-grammar~="purescript"]:not(.insert-mode)':
   'space p t':  'ide-purescript:show-tooltip'
   'space p i':  'ide-purescript:add-module-import'
-  'space p /':  'ide-purescript:search'
   'space p \\': 'ide-purescript:search'
   'space p g':  'ide-purescript:goto-definition'
-  'space p s':  'ide-purescript:show-quick-fixes'
+  'space p f':  'ide-purescript:show-quick-fixes'
+
+'atom-text-editor.vim-mode-plus[data-grammar~="js"]:not(.insert-mode), atom-text-editor.vim-mode-plus[data-grammar~="javascript"]:not(.insert-mode)':
+  'space p r':  'atom-ternjs:rename'
+  'space p \\': 'atom-ternjs:references'
+  'space p d':  'atom-ternjs:documentation'
+  'space p g':  'atom-ternjs:definition'
+  'space p c':  'atom-ternjs:startCompletion'
+  'space p p':  'atom-ternjs:navigateBack'
+  'space p n':  'atom-ternjs:navigateForward'

 ## OMNISHARP
 'atom-text-editor.vim-mode-plus.omnisharp-editor:not(.insert-mode)':
@@ -69,15 +110,7 @@
   'space p t': 'omnisharp-atom:type-lookup'
   'space p g': 'omnisharp-atom:go-to-definition'
   'space p r': 'omnisharp-atom:rename'
-  'space p /': 'omnisharp-atom:find-symbols'
   'space p \\': 'omnisharp-atom:find-symbols'

 'atom-text-editor[data-grammar="text html basic"]:not([mini]), atom-text-editor[data-grammar~="erb"]:not([mini]), atom-text-editor[data-grammar~="jade"]:not([mini]), atom-text-editor[data-grammar~="css"]:not([mini]), atom-text-editor[data-grammar~="stylus"]:not([mini]), atom-text-editor[data-grammar~="sass"]:not([mini]), atom-text-editor[data-grammar~="scss"]:not([mini])':
   'tab': 'emmet:expand-abbreviation-with-tab'
-
-'atom-pane':
-  'ctrl-q': 'core:close'
-
-  # Tab navigation
-  'ctrl-h': 'pane:show-previous-item'
-  'ctrl-l': 'pane:show-next-item'


fixed #78: operators not recognized by session API

--- src/compiler.coffee
+++ src/compiler.coffee
@@ -1,14 +1,18 @@
+[NOUN, VERB, ADVERB, CONJUNCTION] = [1..4]
+
 exec = (aplCode, opts = {}) ->
   ast = parse aplCode, opts
   code = compileAST ast, opts
   env = if prelude then (for frame in prelude.env then frame[..]) else [[]]
   for k, v of ast.vars then env[0][v.slot] = opts.ctx[k]
   result = vm {code, env}
-  for k, v of ast.vars then opts.ctx[k] = env[0][v.slot]
+  for k, v of ast.vars
+    x = opts.ctx[k] = env[0][v.slot]
+    if v.category is ADVERB then x.isAdverb = true
+    if v.category is CONJUNCTION then x.isConjunction = true
   result

 compileAST = (ast, opts = {}) ->
-  [NOUN, VERB, ADVERB, CONJUNCTION] = [1..4]
   ast.scopeDepth = 0
   ast.nSlots = if prelude then prelude.ast.nSlots else 0
   ast.vars = if prelude then Object.create prelude.ast.vars else {}


cooldown finilazation

cooldown finilazation

--- src/cooldown.coffee
+++ src/cooldown.coffee
@@ -12,6 +12,7 @@
     options.target ||= 0
     options.approachBy = 1 unless options.approachBy?

+
     unless I.cooldowns[name]
       I.cooldowns[name] = options


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/drawable.coffee
+++ src/drawable.coffee
@@ -86,6 +86,7 @@
     color: "#196"
     hflip: false
     vflip: false
+    scale: 1
     spriteName: null
     zIndex: 0


Updates the csv snippet

Updates the csv snippet

--- snippets/csv.cson
+++ snippets/csv.cson
@@ -1,4 +1,4 @@
 '.source.inspec':
-  'Desscribe csv':
+  'Describe csv':
     'prefix': 'csv'
-    'body': "# http://inspec.io/docs/reference/resources/csv/\ndescribe csv('${1:name}') do\n  it { should${2:_not} ${3:exist} }${4}\nend"
+    'body': "# http://inspec.io/docs/reference/resources/csv/\ndescribe csv('${1:some_file.csv}') do\n  its('${2:setting}') { should${3:_not} eq ${4:value} }${5}\nend"


properly save new job id

properly save new job id

--- src/kue-worker.coffee
+++ src/kue-worker.coffee
@@ -43,10 +43,10 @@
             console.error error
             done()

-        @createJob(job, intervalTime).
+        newJob = @createJob(job.data, intervalTime).
           save (err) =>
-            debug 'created a job', job.id
-            redis.sadd "interval/job/#{job.data.targetId}", job.id
+            debug 'created a job', newJob.id
+            redis.sadd "interval/job/#{job.data.targetId}", newJob.id
             done(err)

   getTargetJobs: (job, callback=->) =>
@@ -87,8 +87,8 @@

     return timeDiff

-  createJob: (job, intervalTime)=>
-    return queue.create('interval', job.data).
+  createJob: (data, intervalTime)=>
+    return queue.create('interval', data).
       delay(intervalTime).
       removeOnComplete(true).
       attempts(@INTERVAL_ATTEMPTS).


implementing field aliases

implementing field aliases

--- src/mkts-table.coffee
+++ src/mkts-table.coffee
@@ -159,22 +159,29 @@
 @rowheight    = ( me, text ) -> @_set_lanesizes me, 'height',   text

 #-----------------------------------------------------------------------------------------------------------
-@fieldcells = ( me, text ) ->
+@fieldcells = ( me, source ) ->
   @_ensure_grid       me
-  @_ensure_unitvector me
-  text        = text + '..' + text unless contains text, /\.\./
-  d           = IG.GRID.parse_rangekey me.grid, text
+  #.........................................................................................................
+  unless ( match = source.match @fieldcells.source_pattern )?
+    _record_fail me, 'µ6379', """need a text like 'A1:B2:"alias"' or similar for mkts-table/#{fieldcell}, got #{rpr source}"""
+    return null
+  #.........................................................................................................
+  { selector, alias, }  = match.groups
+  selector    = selector + '..' + selector unless contains selector, /\.\./
+  d           = IG.GRID.parse_rangekey me.grid, selector
   designation = IG.CELLS.get_cellkey { colnr: d.left_colnr, rownr: d.top_rownr, }
-  ### TAINT we should allow multiple fields with same designation ###
   if me.fieldcells[ designation ]?
-    throw new Error "(MKTS/TABLE µ5375) unable to redefine field #{designation}: #{rpr text}"
+    throw new Error "(MKTS/TABLE µ5375) unable to redefine field #{designation}: #{rpr source}"
   #.........................................................................................................
   me.fieldcells[ designation ] = d
   for fieldcell from IG.GRID.walk_cells_from_rangeref me.grid, d
     ( me.cellfields[ fieldcell.cellkey ]?= [] ).push designation
+    # if alias?
+    #   ( me.cellfields[ designation ]?= [] ).push fieldcell.cellkey
   #.........................................................................................................
   @_set_default_gaps me, designation
   return null
+@fieldcells.source_pattern = /^\s*(?<selector>[^:\s]+)\s*(?::\s*"(?<alias>[^"]+)")?\s*$/

 #-----------------------------------------------------------------------------------------------------------
 @_set_default_gaps = ( me, designation ) ->


Show the right games

Show the right games

--- src/steps/game.coffee
+++ src/steps/game.coffee
@@ -4,6 +4,11 @@
 fs = require 'fs'
 _ = require "lodash"
 vdf = require 'vdf'
+
+validStateFlags =
+  1: no
+  4: yes
+  32: no

 readACF = (target) ->
   readFile = Rx.Observable.fromNodeCallback fs.readFile
@@ -24,7 +29,10 @@
       readACF(path).map (obj) -> {acfPath: path, data: obj}
     .map ({acfPath, data: {AppState}}) ->
       {path: pathObj.path, i: pathObj.i, gameInfo: AppState, acfPath: acfPath}
-    .filter ({gameInfo}) -> gameInfo.StateFlags is '4'
+    .filter ({gameInfo}) ->
+      state = parseInt(gameInfo.StateFlags)
+      _.all _.pairs(validStateFlags), ([flag, val]) ->
+        ((state & flag) is flag) is val

 buildGameObject = ({path, i, gameInfo, acfPath}) ->
   fullPath = pathMod.join(


fixed a bug with i18n-values where modifying properties

--- src/lib/i18n.coffee
+++ src/lib/i18n.coffee
@@ -47,7 +47,8 @@
           obj  = element
           obj  = obj[path.shift()] while obj and path.length > 1
           if obj
-            obj[path] = i18n.get value, subs
+            path = path[0]
+            obj[path] = i18n.get propExpr, subs
             process element, map if path is 'innerHTML'
         else
           element.setAttribute propName, i18n.get propExpr, subs


tick marks with hidden labels are now shorter

--- src/viz/types/helpers/graph/includes/svg.coffee
+++ src/viz/types/helpers/graph/includes/svg.coffee
@@ -144,10 +144,18 @@
   rotated = vars.x.ticks.rotate isnt 0
   xStyle  = (axis) ->

-    axis
+    groups = axis
       .attr "transform", "translate(0," + vars.axes.height + ")"
       .call vars.x.axis.svg.scale(vars.x.scale.viz)
-      .selectAll("g.tick").select("text")
+      .selectAll("g.tick")
+
+    groups.selectAll("line")
+      .attr "y2", (d) ->
+        d  = +d if d.constructor is Date
+        y2 = d3.select(this).attr("y2")
+        if vars.x.ticks.visible.indexOf(d) >= 0 then y2 else y2/2
+
+    groups.select("text")
         .attr "dy", ""
         .style "text-anchor", if rotated then "end" else "middle"
         .call tickFont, "x"
@@ -181,10 +189,20 @@

   # Draw Y Axis Tick Marks
   yStyle = (axis) ->
-    axis
+
+    groups = axis
       .call vars.y.axis.svg.scale(vars.y.scale.viz)
-      .selectAll("g.tick").select("text")
-        .call tickFont, "y"
+      .selectAll("g.tick")
+
+    groups.selectAll("line")
+      .attr "y2", (d) ->
+        d  = +d if d.constructor is Date
+        y2 = d3.select(this).attr("y2")
+        if vars.x.ticks.visible.indexOf(d) >= 0 then y2 else y2/2
+
+    groups.select("text")
+      .call tickFont, "y"
+
   yAxis = plane.selectAll("g#d3plus_graph_yticks").data axisData
   yAxis.transition().duration(vars.draw.timing).call yStyle
   yAxis.selectAll("line").transition().duration vars.draw.timing


Inserted a IQ stanza to set the users name inside the chat.

--- app/assets/javascripts/app/application/chat.js.coffee
+++ app/assets/javascripts/app/application/chat.js.coffee
@@ -517,6 +517,9 @@
   iq = $iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:roster'})
   Chat.connection.sendIQ iq, Chat.on_roster

+  iq = $iq({type: "set"}).c("vcard", {xmlns: "vcard-temp"}).c("FN", Chat.user_name)
+  Chat.connection.sendIQ iq
+
   Chat.connection.addHandler Chat.on_roster_changed, "jabber:iq:roster", "iq", "set"
   Chat.connection.addHandler Chat.on_message, null, "message", "chat"


show form to edit

show form to edit

--- app/assets/javascripts/bookings/application.js.coffee
+++ app/assets/javascripts/bookings/application.js.coffee
@@ -11,6 +11,16 @@
   d = ['Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday']
   d[@getDay()]

+FormHandler =
+  showForm: (id, start, end, recurrence=1)->
+      $('#template_form').html(templateSlotForm)
+
+      $('#template_slot_day').val(start.getDayName())
+      $('#from_time_hour').val(start.getHours())
+      $('#from_time_minute').val(start.getMinutes())
+      $('#to_time_hour').val(end.getHours())
+      $('#to_time_minute').val(end.getMinutes())
+

 $(document).ready ->
   date = new Date()
@@ -20,6 +30,8 @@

   window.tableSlotCalendar = $("#calendar").fullCalendar(
     eventClick: (event, element) ->
+      console.log event.end
+      FormHandler.showForm(null, event.start, event.end)
       event.title = "CLICKED!"
       $("#calendar").fullCalendar "updateEvent", event

@@ -36,13 +48,7 @@
     selectable: true
     selectHelper: true
     select: (start, end, allDay) ->
-      $('#template_form').html(templateSlotForm)
-
-      $('#template_slot_day').val(start.getDayName())
-      $('#from_time_hour').val(start.getHours())
-      $('#from_time_minute').val(start.getMinutes())
-      $('#to_time_hour').val(end.getHours())
-      $('#to_time_minute').val(end.getMinutes())
+      FormHandler.showForm(null, start, end)

       $('#template_form form').on 'submit', (e) ->
         e.preventDefault()
@@ -64,6 +70,7 @@
             tableSlotCalendar.fullCalendar "renderEvent",
               title: data.id.toString()
               start: start
+              recurrence: data.recurrence
               end: end
               allDay: false
             , true # make the event "stick"


fix collapses without remote content nested in remote nested-many inputs issue

--- app/assets/javascripts/para/inputs/nested_many.coffee
+++ app/assets/javascripts/para/inputs/nested_many.coffee
@@ -73,6 +73,7 @@

   loadCollapseContent: ($target) ->
     targetUrl = $target.data("render-path")
+    return unless targetUrl

     data = {
       "id": $target.data("id")


Clear fields after adding new custom link

--- app/assets/javascripts/refinery/menu_editor.js.coffee
+++ app/assets/javascripts/refinery/menu_editor.js.coffee
@@ -24,6 +24,8 @@
     if url && label
       link_view = new CustomMenuLink({custom_url: url, label: label})
       menuLinkIndex.append(link_view)
+      @$url_field.val('')
+      @$label_field.val('')
     return false

 class NewResourceLinkEditor extends NewLinkEditor


Fix typo on Diners Club stripe.js

Fix typo on Diners Club stripe.js

--- app/assets/javascripts/store/gateway/stripe.js.coffee
+++ app/assets/javascripts/store/gateway/stripe.js.coffee
@@ -11,7 +11,7 @@
   else if (ccType == 'Discover')
     'discover'
   else if (ccType == 'Diners Club')
-    'dinnersclub'
+    'dinersclub'
   else if (ccType == 'JCB')
     'jcb'

@@ -55,4 +55,4 @@
     Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId  + "][month]' value='" + response.card.exp_month + "'/>");
     Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId  + "][year]' value='" + response.card.exp_year + "'/>");
     # Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId  + "][cc_type]' value='" + mapCC(response.card.type) + "'/>");
-    Spree.stripePaymentMethod.parents("form").get(0).submit();+    Spree.stripePaymentMethod.parents("form").get(0).submit();


Add an onChange handler to the marking initialiser Adds an onChange handler which just calls props.onChange with the updated annotation. This is a workaround since @props.annotation is not the current annotation for combo drawing tasks.

--- app/classifier/tasks/drawing/marking-initializer.cjsx
+++ app/classifier/tasks/drawing/marking-initializer.cjsx
@@ -65,7 +65,7 @@
       for key, value of initValues
         mark[key] = value

-    @props.onChange @props.annotation
+    @onChange()

   handleInitDrag: (e) ->
     taskDescription = @props.workflow.tasks[@props.annotation.task]
@@ -78,7 +78,7 @@
       for key, value of initMoveValues
         mark[key] = value

-    @props.onChange @props.annotation
+    @onChange()

   handleInitRelease: (e) ->
     pref = @props.preferences.preferences
@@ -103,7 +103,7 @@
         unless MarkComponent.initValid multiple, @props
           @destroyMark @props.annotation, multiple

-    @props.onChange @props.annotation
+    @onChange()

     if MarkComponent.initValid?
       unless MarkComponent.initValid mark, @props
@@ -114,4 +114,9 @@
       @setState selectedMark: null
     markIndex = annotation.value.indexOf mark
     annotation.value.splice markIndex, 1
-    @props.onChange annotation
+    @onChange()
+
+  onChange: () ->
+    annotations = @props.classification.annotations.slice()
+    newAnnotation = annotations[annotations.length - 1]
+    @props.onChange newAnnotation


opt upload file

opt upload file

--- src/telegram.coffee
+++ src/telegram.coffee
@@ -65,7 +65,7 @@
   formData = _.mapValues options || {}, (i) ->
     if i instanceof fs.ReadStream
       i
-    else if _.isObject(i) and (i.value instanceof fs.ReadStream) and _.isObject(i.options)
+    else if _.isObject(i) and i.value and _.isObject(i.options)
       i
     else if _.isObject(i) || _.isArray(i)
       JSON.stringify(i)


add api events test

add api events test

--- src/test/xml.coffee
+++ src/test/xml.coffee
@@ -335,3 +335,29 @@
         counter++
         æ.equal counter, 5

+    'api events': (æ) ->
+        xml = new Builder
+        xml.on 'end', ->
+            æ.deepEqual results.add,   ['add',   "root", "childA", "childB"]
+            æ.deepEqual results.close, ['close', "childB", "childA", "root"]
+            æ.done()
+
+        results = add:['add'], close:['close']
+
+        xml.on 'add', (el) ->
+            results.add.push el.name
+        xml.on 'close', (el) ->
+            results.close.push el.name
+
+        root = xml.tag('root')
+        c = root.tag('childA')
+        c.tag('childB').end()
+        root.end()
+        c.end()
+        xml.end()
+
+
+
+
+
+


Memory acceess and addressing bugfixes.

Memory acceess and addressing bugfixes.

--- src/CPU.coffee
+++ src/CPU.coffee
@@ -151,7 +151,8 @@
         @memory.read address

     readWord: (address) ->
-        (@readByte address + 1) << 8 | @readByte address
+        highByte = @readByte (address + 1) & 0xFFFF
+        highByte << 8 | @readByte address

     writeByte: (address, value) ->
         @resolveWriteCycles()
@@ -159,7 +160,7 @@

     writeWord: (address, value) ->
         @writeByte address, value & 0xFF
-        @writeByte address + 1, value >> 8
+        @writeByte (address + 1) & 0xFFFF, value >> 8

     ###########################################################
     # Stack pushing / pulling
@@ -283,8 +284,9 @@
     ###########################################################

     relativeMode: =>
+        base = (@programCounter + 1) & 0xFFFF # We need to get address of the next instruction
         offset = @getSignedByte @readNextProgramByte()
-        @getIndexedAddressWord @programCounter, offset
+        @getIndexedAddressWord base, offset

     ###########################################################
     # Indirect addressing modes
@@ -294,8 +296,7 @@
         @readWord @readNextProgramWord()

     indirectXMode: =>
-        address = @getIndexedAddressByte @readNextProgramByte(), @registerX
-        @readWord address
+        @readWord @zeroPageXMode()

     indirectYMode: =>
         base = @readWord @readNextProgramByte()
@@ -306,15 +307,18 @@
     ###########################################################

     getIndexedAddressByte: (base, offset) ->
-        @emptyReadCycle = yes
+        @emptyReadCycle = yes # Included here instead of in operations table just for simplification.
         (base + offset) & 0xFF

     getIndexedAddressWord : (base, offset) ->
-        @emptyReadCycle = yes if (base & 0xFF00) != ((base + offset) & 0xFF00) # Page crossed
+        @emptyReadCycle = yes if @isPageCrossed base, offset
         (base + offset) & 0xFFFF

+    isPageCrossed: (base, offset) ->
+        (base & 0xFF00) != ((base + offset) & 0xFF00)
+
     getSignedByte: (value) ->
-        if value < 0x80 then value else value - 0xFF
+        if value >= 0x80 then value - 0x100 else value

     ###########################################################
     # No operation instruction


Fix: viewing post on another entity domain shows mentions your server has seen

--- assets/javascripts/views/posts/conversation.js.coffee
+++ assets/javascripts/views/posts/conversation.js.coffee
@@ -16,7 +16,7 @@
     url = if TentStatus.config.domain_entity.assertEqual(@entity)
       "#{TentStatus.config.current_tent_api_root}/posts/#{@post_id}"
     else
-      "#{TentStatus.config.current_tent_api_root}/posts/#{encodeURIComponent @entity}/#{@post_id}"
+      "#{TentStatus.config.tent_api_root}/posts/#{encodeURIComponent @entity}/#{@post_id}"
     new HTTP 'GET', url, null, (post, xhr) =>
       return unless xhr.status == 200
       post = new TentStatus.Models.Post post
@@ -24,7 +24,7 @@
       @set 'post', post

       @on 'change:child_posts', @render
-      new HTTP 'GET', "#{TentStatus.config.current_tent_api_root}/posts", {
+      new HTTP 'GET', "#{TentStatus.config.tent_api_root}/posts", {
         limit: TentStatus.config.PER_PAGE
         mentioned_post: @post_id
       }, (posts, xhr) =>
@@ -39,7 +39,7 @@
       post_id = @post.postMentions()[0].post

       @on 'change:parent_post', @render
-      new HTTP 'GET', "#{TentStatus.config.current_tent_api_root}/posts/#{encodeURIComponent entity}/#{post_id}", null, (post, xhr) =>
+      new HTTP 'GET', "#{TentStatus.config.tent_api_root}/posts/#{encodeURIComponent entity}/#{post_id}", null, (post, xhr) =>
         return unless xhr.status == 200
         post = new TentStatus.Models.Post post
         @set 'parent_post', post


Remove juno -p option, since its update solves this

--- atom/atom.symlink/config.cson
+++ atom/atom.symlink/config.cson
@@ -29,10 +29,7 @@
   "julia-client":
     consoleOptions: {}
     firstBoot: false
-    juliaOptions:
-      startupArguments: [
-        "-p 2"
-      ]
+    juliaOptions: {}
     uiOptions:
       enableMenu: true
       enableToolBar: true


Update browsers popularity

Update browsers popularity


feat: promisify sender

feat: promisify sender

--- src/observers/incidentsApi.observer.coffee
+++ src/observers/incidentsApi.observer.coffee
@@ -1,4 +1,5 @@
 _ = require "lodash"
+Promise = require "bluebird"
 { ServiceBusClient } = require("@azure/service-bus")
 { encode } = require "url-safe-base64"
 debug = require("debug") "notification-processor:observers:incidents-api"
@@ -13,26 +14,33 @@
       observable.on "unsuccessful_non_retryable", @publishToTopic

     publishToTopic: ({ id, notification, error }) =>
-      message = { body: JSON.stringify @_mapper(id, notification, error.cause) }
-      debug "To publish message %o", message
-      @messageSender.send(message)
+      $message = Promise.props { body: JSON.stringify @_mapper(id, notification, error.cause) }
+      $message
+      .tap (message) => debug "To publish message %o", message
+      .then (message) => @messageSender.send message

     _mapper: (id, notification, err) ->
-      resource = @sender.resource notification
-
-      {
-        id: encode [@app, @job, resource].join("_")
-        @app
-        @job
-        resource: "#{ resource }"
-        notification: notification
-        user: "#{ @sender.user(notification) }"
-        @clientId
-        error: _.omit err, "detail.request"
-        request: _.omit _.get(err, "detail.request"), @propertiesToOmit
-        type: _.get err, "type", "unknown_error"
-        tags: _.get err, "tags", []
-      }
+
+      Promise.promisifyAll @sender
+
+      __stringifySenderResult = (asyncFn) =>
+        asyncFn notification
+          .then (result) => "#{ result }"
+
+      Promise.props
+        {
+          id: encode [@app, @job, resource].join("_")
+          @app
+          @job
+          resource: __stringifySenderResult @sender.resourceAsync
+          notification: notification
+          user: __stringifySenderResult @sender.user
+          @clientId
+          error: _.omit err, "detail.request"
+          request: _.omit _.get(err, "detail.request"), @propertiesToOmit
+          type: _.get err, "type", "unknown_error"
+          tags: _.get err, "tags", []
+        }

     _buildMessageSender: (connectionString, topic) ->
       ServiceBusClient


Todos are in trello

Todos are in trello

--- src/app.coffee
+++ src/app.coffee
@@ -4,12 +4,6 @@

 todo = require "./modules/todo/index.coffee"

-
-# TODO Navigation and routing
-# TODO Keep main layout. Place proper route partials inside of it.
-# TODO electrolyte dependency injection
-# TODO ba.js animation
-# TODO Remove todo list. Lol.
 m.route.mode = "search"
 m.route document, "/todo",
  "/todo": todo


fix two-sided pin assignment

fix two-sided pin assignment

--- src/symbol/default/common/two-sided.coffee
+++ src/symbol/default/common/two-sided.coffee
@@ -7,7 +7,7 @@
   schematic.showPinNames ?= false

   # Add pins if no any
-  unless element.pinGroups.length
+  unless Object.keys(element.pinGroups).length
     element.pins[1] = { name: leftName, number: 1 }
     element.pins[2] = { name: rightName, number: 2 }
     element.pinGroups[leftName] = [1]


Delay actually setting the position until button show to reduce button jumpiness

--- js-library/app/js/jail_iframe/classes/buttons.coffee
+++ js-library/app/js/jail_iframe/classes/buttons.coffee
@@ -13,13 +13,15 @@
   stopLoading:  => @$el.removeClass  "fl-loading"

   setCoordinates: (top, left) =>
+    @_top = top
+    @_left = left
 #    return if @$el.hasClass 'active'
     console.log 'setting position'
-    FactlinkJailRoot.set_position_of_element top, left, window, @frame.$el

   show: =>
     @stopLoading()
     console.log @el.className
+    FactlinkJailRoot.set_position_of_element @_top, @_left, window, @frame.$el
     #TODO:what's this line do?
     #FactlinkJailRoot.$factlinkCoreContainer.find('div.fl-button').removeClass('active')
     @$el.addClass 'active'


msgflo-register: Don't log --forever

msgflo-register: Don't log --forever

--- src/utils/register-foreign-multiple.coffee
+++ src/utils/register-foreign-multiple.coffee
@@ -55,7 +55,6 @@
           Promise.resolve definition
   .then (definitions) ->
     onComplete() unless program.forever
-    console.log '--forever enabled'
     setInterval ->
       Promise.map definitions, (definition) ->
         register messaging, definition


added a passthrough to the git.coffee script to run raw git commands against a repo

--- src/git.coffee
+++ src/git.coffee
@@ -15,6 +15,11 @@
     bash     = "#{Git.bin} #{command} #{options} #{args}"
     exec bash, {cwd: git_dir}, callback
     return bash
+
+  # Public: Passthrough for raw git commands
+  #
+  git.cmd  = (command, options, args, callback) ->
+    git command, options, args, callback

   # Public: Get a list of the remote names.


Hide tooltip so doesn't block clicks fixes #3

--- src/index.cjsx
+++ src/index.cjsx
@@ -88,6 +88,7 @@
             scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft

             tooltip
+              .style("visibility", "visible")
               .transition()
               .duration(100)
               .style("opacity", 1)
@@ -102,6 +103,7 @@
               .transition()
               .duration(250)
               .style("opacity", 1/1e6)
+              .each("end", -> tooltip.style("visibility", "hidden"))
         )

     if @props.xAxis


Cleanup due to comment

Cleanup due to comment

--- client/Social/Activity/views/embedbox/embedboxlinkviewprovider.coffee
+++ client/Social/Activity/views/embedbox/embedboxlinkviewprovider.coffee
@@ -7,6 +7,17 @@

   viewAppended: JView::viewAppended
   pistachio:->
-    """
-    #{@getData().link_embed?.provider_name or @getData().provider_name or 'the internet'}#{if (@getData().link_embed?.provider_url or @getData().provider_url) then " at "+(@getData().link_embed?.provider_display or @getData().provider_display)+'' else ''}
-    """
+    data = @getData()
+
+    {link_embed, provider_name, provider_url, provider_display} = data
+
+    link_embed       or= {}
+    provider_name    or= link_embed.provider_name    or ''
+    provider_url     or= link_embed.provider_url
+    provider_display or= link_embed.provider_display or ''
+
+    if provider_url
+    then provider_link = "at #{provider_display}"
+    else provider_link = ''
+
+    "#{provider_name}#{provider_link}"


activity: self heal after errors on new private channel modal

--- client/activity/lib/components/createprivatechannelmodal/index.coffee
+++ client/activity/lib/components/createprivatechannelmodal/index.coffee
@@ -140,9 +140,11 @@

     @_isCreating = yes

-    createPrivateChannel(options).then ({channel}) =>
-
-      kd.singletons.router.handleRoute "/Messages/#{channel.id}"
+    createPrivateChannel(options)
+      .then ({channel}) ->
+        kd.singletons.router.handleRoute "/Messages/#{channel.id}"
+      .catch =>
+        @_isCreating = no

   onChange: (event) ->


Removing leftover console.log

Removing leftover console.log

--- src/assets.coffee
+++ src/assets.coffee
@@ -105,7 +105,6 @@
           if @options.buildDir
             buildPath = path.join process.cwd(), @options.buildDir, filename
             mkdirRecursive path.dirname(buildPath), 0755, (err) ->
-              console.log err if err
               fs.writeFile buildPath, concatenation
           return ["/#{filename}"]
         else


Optimized State transition for Menu Button

--- watch.framer/app.coffee
+++ watch.framer/app.coffee
@@ -165,6 +165,8 @@
 menuBtnOpenLayer.states.add 'hidden',
 	opactiy: 0
 	scale: 0
+	rotation: -90
+	blur: 5

 menuBtnOpenLayer.states.animationOptions =
 	curve: 'bezier-curve'
@@ -173,6 +175,8 @@
 menuBtnCloseLayer.states.add 'hidden',
 	opactiy: 0
 	scale: 0
+	rotation: 90
+	blur: 5

 menuBtnCloseLayer.states.animationOptions =
 	curve: 'bezier-curve'


bindable

bindable

--- src/bindable.coffee
+++ src/bindable.coffee
@@ -35,7 +35,7 @@
   #or
   yourObject.bind "anotherCustomEvent", ->
     doSomething()
-

+

   @name bind
   @methodOf Bindable#


object_extensions

--- test/object_extensions.coffee
+++ test/object_extensions.coffee
@@ -39,5 +39,10 @@
   equals object.b, "b"
   equals object.c, "c"

+test "isObject", ->
+  object = {}
+
+  equals Object.isObject(object), true
+
 module()


Encapsulate request defaults to DRY up the code

--- src/checkout.coffee
+++ src/checkout.coffee
@@ -31,6 +31,9 @@
 class Checkout

   HOST_URL = window.location.origin
+
+  events =
+    ORDER_FORM_UPDATED: 'orderFormUpdated.vtex'

   constructor: (options = {}) ->
     HOST_URL = options.hostURL if options.hostURL
@@ -67,34 +70,51 @@
         'openTextField'
       ]

+  ###
+  PRIVATE METHODS
+  ###
+
   _cacheOrderForm: (data) =>
     @orderFormId = data.orderFormId
     @orderForm = data

-  broadcastOrderForm = (orderForm) ->
-    $(window).trigger('orderFormUpdated.vtex', orderForm)
-
-  orderFormHasExpectedSections = (orderForm, sections) ->
+  _triggerEvent: (event) -> (orderForm) ->
+    $(window).trigger(event, orderForm)
+
+  _orderFormHasExpectedSections: (orderForm, sections) ->
     if not orderForm or not orderForm instanceof Object
       return false
     for section in sections
       return false if not orderForm[section]
     return true

+  # $.ajax wrapper with common defaults.
+  # Used to encapsulate requests which have side effects and should broadcast results
+  _updateOrderForm: (options) =>
+    throw new Error("options.url is required when sending request") unless options?.url
+
+    # Defaults
+    options.type or= 'POST'
+    options.contentType or= 'application/json; charset=utf-8'
+    options.dataType or= 'json'
+
+    @ajax(options)
+      .done(@_cacheOrderForm)
+      .done(@_triggerEvent(events.ORDER_FORM_UPDATED))
+
+  ###
+  PUBLIC METHODS
+  ###
+
   # Sends an idempotent request to retrieve the current OrderForm.
   getOrderForm: (expectedFormSections = @_allOrderFormSections) =>
-    if orderFormHasExpectedSections(@orderForm, expectedFormSections)
+    if @_orderFormHasExpectedSections(@orderForm, expectedFormSections)
       return @promise(@orderForm)
     else
       checkoutRequest = { expectedOrderFormSections: expectedFormSections }
-      @ajax
+      @_updateOrderForm
         url: @_getBaseOrderFormURL()
-        type: 'POST'
-        contentType: 'application/json; charset=utf-8'
-        dataType: 'json'
         data: JSON.stringify(checkoutRequest)
-      .done(@_cacheOrderForm)
-      .done(broadcastOrderForm)

   # Sends an OrderForm attachment to the current OrderForm, possibly updating it.
   sendAttachment: (attachmentId, attachment, expectedOrderFormSections = @_allOrderFormSections, options = {}) =>
@@ -105,14 +125,9 @@

     attachment['expectedOrderFormSections'] = expectedOrderFormSections

-    xhr = @ajax
+    xhr = @_updateOrderForm
       url: @_getSaveAttachmentURL(attachmentId)
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(attachment)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

     if options.abort and options.subject
       @_subjectToJqXHRMap[options.subject]?.abort()
@@ -131,14 +146,9 @@
       info: offeringInfo
       expectedOrderFormSections: expectedOrderFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getAddOfferingsURL(itemIndex)
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(updateItemsRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to add an offering to the OrderForm.
   addOffering: (offeringId, itemIndex, expectedOrderFormSections) =>
@@ -150,14 +160,9 @@
       Id: offeringId
       expectedOrderFormSections: expectedOrderFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getRemoveOfferingsURL(itemIndex, offeringId)
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(updateItemsRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to update the items in the OrderForm. Items that are omitted are not modified.
   updateItems: (items, expectedOrderFormSections = @_allOrderFormSections) =>
@@ -168,15 +173,10 @@
     if @_requestingItem isnt undefined
       @_requestingItem.abort()

-    return @_requestingItem = @ajax
+    return @_requestingItem = @_updateOrderForm
       url: @_getUpdateItemURL()
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(updateItemsRequest)
     .done(=> @_requestingItem = undefined)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to select an available gift
   updateSelectableGifts: (list, selectedGifts, expectedOrderFormSections = @_allOrderFormSections) =>
@@ -188,15 +188,10 @@
     if @_requestingSelectableGifts isnt undefined
       @_requestingSelectableGifts.abort()

-    return @_requestingSelectableGifts = @ajax
+    return @_requestingSelectableGifts = @_updateOrderForm
       url: @_getUpdateSelectableGifts(list)
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(updateSelectableGiftsRequest)
     .done(=> @_requestingSelectableGifts = undefined)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to remove items from the OrderForm.
   removeItems: (items, expectedOrderFormSections = @_allOrderFormSections) =>
@@ -217,14 +212,9 @@
       text: couponCode
       expectedOrderFormSections: expectedOrderFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getAddCouponURL()
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify couponCodeRequest
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to remove the discount coupon from the OrderForm.
   removeDiscountCoupon: (expectedOrderFormSections) =>
@@ -233,14 +223,9 @@
   # Sends a request to remove the gift registry for the current OrderForm.
   removeGiftRegistry: (expectedFormSections = @_allOrderFormSections) =>
     checkoutRequest = { expectedOrderFormSections: expectedFormSections }
-    @ajax
+    @_updateOrderForm
       url: @_getRemoveGiftRegistryURL()
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(checkoutRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to add an attachment to a specific item
   addItemAttachment: (itemIndex, attachmentName, content, expectedFormSections = @_allOrderFormSections) =>
@@ -248,14 +233,9 @@
       content: content
       expectedOrderFormSections: expectedFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getItemAttachmentURL(itemIndex, attachmentName)
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(dataRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to remove an attachment of a specific item
   removeItemAttachment: (itemIndex, attachmentName, content, expectedFormSections = @_allOrderFormSections) =>
@@ -263,14 +243,10 @@
       content: content
       expectedOrderFormSections: expectedFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getItemAttachmentURL(itemIndex, attachmentName)
       type: 'DELETE'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(dataRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Send a request to add an attachment to a bunle item
   addBundleItemAttachment: (itemIndex, bundleItemId, attachmentName, content, expectedFormSections = @_allOrderFormSections) =>
@@ -278,14 +254,9 @@
       content: content
       expectedOrderFormSections: expectedFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getBundleItemAttachmentURL(itemIndex, bundleItemId, attachmentName)
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(dataRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to remove an attachmetn from a bundle item
   removeBundleItemAttachment: (itemIndex, bundleItemId, attachmentName, content, expectedFormSections = @_allOrderFormSections) =>
@@ -293,14 +264,10 @@
       content: content
       expectedOrderFormSections: expectedFormSections

-    @ajax
+    @_updateOrderForm
       url: @_getBundleItemAttachmentURL(itemIndex, bundleItemId, attachmentName)
       type: 'DELETE'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify(dataRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to calculates shipping for the current OrderForm, given a COMPLETE address object.
   calculateShipping: (address) =>
@@ -308,7 +275,7 @@

   # Simulates shipping using a list of items, a postal code and a country.
   simulateShipping: (items, postalCode, country) =>
-    data =
+    dataRequest =
       items: items
       postalCode: postalCode
       country: country
@@ -318,7 +285,7 @@
       type: 'POST'
       contentType: 'application/json; charset=utf-8'
       dataType: 'json'
-      data: JSON.stringify(data)
+      data: JSON.stringify(dataRequest)

   # Given an address with postal code and a country, retrieves a complete address, when available.
   getAddressInformation: (address) =>
@@ -345,15 +312,9 @@
       interestValue: interestValue
       expectedOrderFormSections : expectedOrderFormSections
     }
-    # TODO 'falhar' a promise caso a propriedade 'receiverUri' esteja null
-    @ajax
+    @_updateOrderForm
       url: @_startTransactionURL(),
-      type: 'POST',
-      contentType: 'application/json; charset=utf-8',
-      dataType: 'json',
       data: JSON.stringify(transactionRequest)
-    .done(@_cacheOrderForm)
-    .done(broadcastOrderForm)

   # Sends a request to retrieve the orders for a specific orderGroupId.
   getOrders: (orderGroupId) =>
@@ -376,11 +337,8 @@
   # Sends a request to remove a payment account from the OrderForm.
   removeAccountId: (accountId) =>
     removeAccountIdRequest = { expectedOrderFormSections: [] }
-    @ajax
+    @_updateOrderForm
       url: @_getOrderFormURL() + '/paymentAccount/' + accountId + '/remove'
-      type: 'POST'
-      contentType: 'application/json; charset=utf-8'
-      dataType: 'json'
       data: JSON.stringify removeAccountIdRequest

   # URL to redirect the user to when he chooses to logout.


Renamed Client#submit to Client#submitTask.

--- src/client.coffee
+++ src/client.coffee
@@ -15,7 +15,7 @@
   # Submits a task with the given name and data.
   #
   # Returns a handle to the task.
-  submit: (name, data, callback) ->
+  submitTask: (name, data, callback) ->
     handle = new Handle name, data, callback
     @_addHandle handle
     payload = JSON.stringify id: handle.id, request: name, data: data


Changed port again to test hosting

Changed port again to test hosting

--- src/client.coffee
+++ src/client.coffee
@@ -27,7 +27,7 @@
 					context.fillRect(x, y, 9, 9)

 		connect = ->
-			server = new io.Socket("snake.9elements.com")
+			server = new io.Socket("snake.9elements.com", { 'port': 5000 })
 			server.connect()
 			server.on "message", (event) ->
 				message = JSON.parse(event)


:racehorse: Transact setSchema config changes

--- src/config.coffee
+++ src/config.coffee
@@ -786,9 +786,10 @@
         rootSchema = properties[key]

     Object.assign rootSchema, schema
-    @setDefaults(keyPath, @extractDefaultsFromSchema(schema))
-    @setScopedDefaultsFromSchema(keyPath, schema)
-    @resetSettingsForSchemaChange()
+    @transact =>
+      @setDefaults(keyPath, @extractDefaultsFromSchema(schema))
+      @setScopedDefaultsFromSchema(keyPath, schema)
+      @resetSettingsForSchemaChange()

   load: ->
     @initializeConfigDirectory()


generate model files with dash

generate model files with dash

--- src/generate.coffee
+++ src/generate.coffee
@@ -6,7 +6,7 @@

 createScripts = (modelName, dirname, options = {}) ->

-    ModelName = modelName.charAt(0).toUpperCase() + modelName.slice(1)
+    ModelName = (name.charAt(0).toUpperCase() + name.slice(1) for name in modelName.split('-')).join('')

     fs.writeFileSync "#{dirname}/#{modelName}.coffee", renderer.render('entity.coffee', model: modelName, Model: ModelName)
     fs.writeFileSync "#{dirname}/#{modelName}-factory.coffee", renderer.render('factory.coffee', model: modelName, Model: ModelName)


Client: app: remove follow buttons from memberlistitemview

--- client/app/lib/commonviews/memberslistitemview.coffee
+++ client/app/lib/commonviews/memberslistitemview.coffee
@@ -2,7 +2,6 @@
 kd = require 'kd'
 KDListItemView = kd.ListItemView
 AvatarView = require './avatarviews/avatarview'
-FollowButton = require './followbutton'
 JCustomHTMLView = require '../jcustomhtmlview'
 ProfileLinkView = require './linkviews/profilelinkview'

@@ -28,28 +27,8 @@

     @actor = new ProfileLinkView {}, data

-    @followersAndFollowing = new JCustomHTMLView
-      cssClass  : 'user-numbers'
-      pistachio : "{{ #(counts.followers)}} followers {{ #(counts.following)}} following"
-    , data
-
-    unless data.getId() is whoami().getId()
-      @followButton = new FollowButton
-        title          : "follow"
-        icon           : yes
-        style          : 'solid green medium'
-        stateOptions   :
-          unfollow     :
-            title      : "unfollow"
-            cssClass   : 'following-account'
-            style      : 'solid gray medium'
-        dataType       : 'JAccount'
-      , data
-
   viewAppended:->
     @addSubView @avatar
-    @addSubView @followButton if @followButton
     @addSubView @actor
-    @addSubView @followersAndFollowing


fix reactivity issue with positions

fix reactivity issue with positions

--- client/positions/position-detail.controller.ng.coffee
+++ client/positions/position-detail.controller.ng.coffee
@@ -1,23 +1,22 @@
 'use strict'

 angular.module 'atsApp'
-.controller 'PositionDetailCtrl', ($scope, $stateParams, $meteor) ->
-  $scope.position = $scope.$meteorObject Positions, $stateParams.positionId
+.controller 'PositionDetailCtrl', ($scope, $stateParams, $meteor, $state) ->
+  $scope.position = $scope.$meteorObject Positions, $stateParams.positionId, false
   $scope.$meteorSubscribe('positions')

   $scope.companies = $scope.$meteorCollection () ->
     Companies.find {}, {sort:$scope.getReactively('sort')}

   $meteor.autorun $scope, () ->
-    $scope.$meteorSubscribe('companies', {
-      sort: $scope.getReactively('sort')
-    })
+    $scope.$meteorSubscribe('companies')

   $scope.save = () ->
     if $scope.form.$valid
       $scope.position.save().then(
         (numberOfDocs) ->
           console.log 'save successful, docs affected ', numberOfDocs
+          $state.go 'positions-list'
         (error) ->
           console.log 'save error ', error
       )


Test for #17

Test for #17

--- spec/markdown-table-formatter-spec.coffee
+++ spec/markdown-table-formatter-spec.coffee
@@ -320,6 +320,25 @@
       "|:-----|:------|:-----|:-----|:--------|\n"+
       "| asd  |       |      |      |         |\n"+
       "| dsa  |       |      |      |         |\n"
+  ,
+    # regression test for #17
+    test:
+      """
+      | **Name**        | **Unicode**                           | **Unicode Name**                                      | **ASCII Dec**  |
+      |:----------------|:--------------------------------------|:------------------------------------------------------|:---------------|
+      | Digits          | The code points U+0030 through U+0039 | DIGIT ZERO through DIGIT NINE                         | 48 through 57  |
+      | CAPITAL-LETTERS | The code points U+0041 through U+005A | LATIN CAPITAL LETTER A through LATIN CAPITAL LETTER Z | 65 through 90  |
+      | SMALL-LETTERS   | The code points U+0061 through U+007A | LATIN SMALL LETTER A through LATIN SMALL LETTER Z     | 97 through 122 |
+      """
+    expected:
+      """
+      | **Name**        | **Unicode**                           | **Unicode Name**                                      | **ASCII Dec**  |
+      |:----------------|:--------------------------------------|:------------------------------------------------------|:---------------|
+      | Digits          | The code points U+0030 through U+0039 | DIGIT ZERO through DIGIT NINE                         | 48 through 57  |
+      | CAPITAL-LETTERS | The code points U+0041 through U+005A | LATIN CAPITAL LETTER A through LATIN CAPITAL LETTER Z | 65 through 90  |
+      | SMALL-LETTERS   | The code points U+0061 through U+007A | LATIN SMALL LETTER A through LATIN SMALL LETTER Z     | 97 through 122 |
+
+      """
   ]
   nonTables=[
     "aaa|dafdas|adfas\n"+


fixes

fixes


Varargs convention

Varargs convention

--- src/entity.coffee
+++ src/entity.coffee
@@ -470,7 +470,7 @@
   # After calling, this entity will automatically activate
   # collectables in the specified group on contact.
   #
-  # names... - An arbitrary list of String group names of collectable entities
+  # names... - Varargs list of String group names of collectable entities
   #
   # Ex:
   #
@@ -528,7 +528,7 @@
   # ---------------------
   # Public: An interface for including composable mixins or modules
   #
-  # objs... - An arbitrary list of 'module' objects, implementing functions to add to the entity
+  # objs... - Varargs list of 'module' objects, implementing functions to add to the entity
   #           e.g., `@include Killable` or `@include Killable, Resettable`
   #
   # Ex:


refactor functions and add comments

refactor functions and add comments

--- src/garble.coffee
+++ src/garble.coffee
@@ -29,32 +29,43 @@
 SHOW_TRANSLATION_PATH = process.env.HUBOT_GARBLE_TRANSLATION_PATH_LOG || true
 DEFAULT_ITERATIONS = 5

-getRandomLanguages = (count) ->
-  # an array of all available language codes except LOCAL_LANGUAGE
-  languageCodes = _.chain(LANGUAGES).pluck('code').pull(LOCAL_LANGUAGE).value()
+# get full language name from a language code
+getLanguageName = (languageCode) ->
+  _.result(_.find(LANGUAGES, 'code', languageCode), 'language')

-  # an array of randomly sorted languages
-  randomLanguages = _.times count, () ->
+# an array of all available language codes except LOCAL_LANGUAGE
+getLanguageCodes = () ->
+  _.chain(LANGUAGES).pluck('code').pull(LOCAL_LANGUAGE).value()
+
+# an array of randomly sorted languages
+getRandomLanguages = (languageCodes, amount) ->
+  _.times amount, () ->
     lang = _.sample(languageCodes)
     _.pull(languageCodes, lang)
     lang

-  # add LOCAL_LANGUAGE as first and last items
-  _.chain(randomLanguages).unshift(LOCAL_LANGUAGE).push(LOCAL_LANGUAGE).value()
+# an array of languages to translate text through
+# wraps LOCAL_LANGUAGE around random assortment of languages
+getTranslationPath = (amount) ->
+  _.chain(getRandomLanguages(getLanguageCodes(), amount))
+    .unshift(LOCAL_LANGUAGE)
+    .push(LOCAL_LANGUAGE)
+    .value()

-getRequestString = (langFrom, langTo, text) ->
+# a string that indicates what "translation path" the text was passed through
+getTranslationPathLog = (languageCodes) ->
+  languageNames = _.map languageCodes, (code) -> getLanguageName(code)
+  "translation path: #{languageNames.join(' → ')}"
+
+# a URI that satisfies the Yandex API requirements
+getRequestURI = (langFrom, langTo, text) ->
   opts =
     key: API_KEY
     lang: "#{langFrom}-#{langTo}"
     text: text
   return "#{TRANSLATE_URI}?#{querystring.stringify(opts)}"

-logTranslationPath = (languageCodes) ->
-  # get full language name from language code
-  languageNames = _.map languageCodes, (lang) ->
-    _.result(_.find(LANGUAGES, 'code', lang), 'language')
-  "translation path: #{languageNames.join(' -> ')}"
-
+# a string of translated text
 parseResponse = (str) ->
   try
     return JSON.parse(str).text[0]
@@ -66,14 +77,14 @@
   robot.respond /garble (.*)/i, (msg) ->

     text = msg.match[1]?.trim()
-    langs = getRandomLanguages(DEFAULT_ITERATIONS)
+    langs = getTranslationPath(DEFAULT_ITERATIONS)

-    request getRequestString(langs[0], langs[1], text), (error, response, body) ->
-      request getRequestString(langs[1], langs[2], parseResponse(body)), (error, response, body) ->
-        request getRequestString(langs[2], langs[3], parseResponse(body)), (error, response, body) ->
-          request getRequestString(langs[3], langs[4], parseResponse(body)), (error, response, body) ->
-            request getRequestString(langs[4], langs[5], parseResponse(body)), (error, response, body) ->
-              request getRequestString(langs[5], langs[6], parseResponse(body)), (error, response, body) ->
+    request getRequestURI(langs[0], langs[1], text), (error, response, body) ->
+      request getRequestURI(langs[1], langs[2], parseResponse(body)), (error, response, body) ->
+        request getRequestURI(langs[2], langs[3], parseResponse(body)), (error, response, body) ->
+          request getRequestURI(langs[3], langs[4], parseResponse(body)), (error, response, body) ->
+            request getRequestURI(langs[4], langs[5], parseResponse(body)), (error, response, body) ->
+              request getRequestURI(langs[5], langs[6], parseResponse(body)), (error, response, body) ->
                 msg.send parseResponse(body)
                 unless SHOW_TRANSLATION_PATH == 'false'
-                  msg.send logTranslationPath(langs)
+                  msg.send getTranslationPathLog(langs)


Fix a warning for Travis tests

Fix a warning for Travis tests

--- tests/models_konnector.coffee
+++ tests/models_konnector.coffee
@@ -63,6 +63,7 @@
         konnector.fieldValues.password.should.equal 'testpass'

     it 'remove encrypted fields from normal fields', ->
+        konnector.id = '123'
         konnector.removeEncryptedFields konnectorHash.test.fields
         should.not.exist konnector.fieldValues.password


fix issue with tab delimited files

fix issue with tab delimited files

--- lib/csv-editor-form-element.coffee
+++ lib/csv-editor-form-element.coffee
@@ -328,7 +328,7 @@
     if delimiter is 'custom'
       options.delimiter = @columnDelimiterTextEditor.getText()
     else
-      options.delimiter = delimiter
+      options.delimiter = denormalizeValue(delimiter)

     if rowDelimiter is 'custom'
       options.rowDelimiter = @rowDelimiterTextEditor.getText()


allow explicit dependency ids

allow explicit dependency ids

--- src/hinoki.coffee
+++ src/hinoki.coffee
@@ -42,21 +42,40 @@

         return null

-    inject: (arg, fun) ->
-        containers = if Array.isArray arg then arg else [arg]
+    handleInjectArguments: (arg1, arg2, arg3) ->
+        object = {}
+        object.containers = if Array.isArray arg1 then arg1 else [arg1]

-        containers.forEach (c) ->
+        object.containers.forEach (c) ->
             unless c? and 'object' is typeof c
-                throw new Error 'the first argument to inject must be an object or an array of objects'
+                throw new Error 'the 1st argument to inject must be an object or an array of objects'

-        containers.forEach (c) ->
+        object.containers.forEach (c) ->
             unless c.instances?
                 c.instances = {}

-        dependencyIds = module.exports.parseFunctionArguments fun
+        if arg3?
+            unless 'function' is typeof arg3
+                throw new Error 'the 3rd argument to inject is optional but must be a function if provided'
+            object.ids = if Array.isArray arg2 then arg2 else [arg2]
+            object.ids.forEach (id) ->
+                unless id? and 'string' is typeof id
+                    throw new Error 'the 2nd argument to inject must be a string or an array of strings if a 3rd argument is provided'
+            object.fun = arg3

-        module.exports.resolve containers, dependencyIds, [], ->
-            fun.apply null, arguments
+        else
+            unless 'function' is typeof arg2
+                throw new Error 'the 2nd argument to inject must be a function if no 3rd argument is provided'
+            object.ids = module.exports.parseFunctionArguments arg2
+            object.fun = arg2
+
+        object
+
+    inject: ->
+        namedArgs = module.exports.handleInjectArguments.apply null, arguments
+
+        module.exports.resolve namedArgs.containers, namedArgs.ids, [], ->
+            namedArgs.fun.apply null, arguments

     resolve: (containers, dependencyIds, chain, cb) ->
         hasErrorOccured = false


[neo4j] added follower filter just to see JAccount in both side

--- server/lib/server/graph/graph.coffee
+++ server/lib/server/graph/graph.coffee
@@ -153,7 +153,7 @@
     query = [
       'start koding=node:koding(id={groupId})'
       'MATCH koding-[:member]->followees<-[r:follower]-follower'
-      'where followees.name="JAccount" and r.createdAt > {startDate} and r.createdAt < {endDate}'
+      'where followees.name="JAccount" and follower.name="JAccount" and r.createdAt > {startDate} and r.createdAt < {endDate}'
       'return r,followees, follower'
       'order by r.createdAt DESC'
       'limit 10'


Epoch.Formats.seconds test fail.

Epoch.Formats.seconds test fail.

Test fail when tested on a machine with timezone GMT+2.

--- tests/unit/core/format.coffee
+++ tests/unit/core/format.coffee
@@ -65,4 +65,4 @@

   describe 'seconds', ->
     it 'should return a well formatted date given a timestamp', ->
-      assert.equal Epoch.Formats.seconds(1404385979), '04:12:59 AM'
+      assert.match Epoch.Formats.seconds(1404385979), /\d{2}:\d{2}:\d{2} AM|PM/


fixup AuthenticationController from missing module after merge

--- services/web/app/coffee/Features/Analytics/AnalyticsController.coffee
+++ services/web/app/coffee/Features/Analytics/AnalyticsController.coffee
@@ -1,15 +1,15 @@
 AnalyticsManager = require "./AnalyticsManager"
 Errors = require "../Errors/Errors"
-
+AuthenticationController = require("../Authentication/AuthenticationController")

 module.exports = AnalyticsController =
 	recordEvent: (req, res, next) ->
 		user_id = AuthenticationController.getLoggedInUserId(req) or req.sessionID
 		AnalyticsManager.recordEvent user_id, req.params.event, req.body, (error) ->
-			if error?
-				if error instanceof Errors.ServiceNotConfiguredError
-					# ignore, no-op
-					return res.send(204)
-				else
-					return next(error)
-			res.send 204
+			if error instanceof Errors.ServiceNotConfiguredError
+				# ignore, no-op
+				return res.send(204)
+			else if error?
+				return next(error)
+			else
+				return res.send 204


When adding globals, also add them to the currently executing function.

--- src/aether.coffee
+++ src/aether.coffee
@@ -18,7 +18,10 @@

 module.exports = class Aether
   @execution: execution
-  @addGlobal: protectBuiltins.addGlobal  # Use before instantiating Aether instances
+  @addGlobal: (name, value) ->
+    protectBuiltins.addGlobal name, value
+    if aether.esperEngine?
+      aether.esperEngine.addGlobal name, value
   @replaceBuiltin: protectBuiltins.replaceBuiltin
   @globals: protectBuiltins.addedGlobals


fix(tests/authFrame): update to expect an Error instead of true

--- test/vk.coffee
+++ test/vk.coffee
@@ -252,7 +252,7 @@
           onFail()

       vk.authFrame ( error ) ->
-        expect( error ).to.equal true
+        expect( error ).to.be.instanceof Error
         done()


vm.set(): correctly count limits for CPUs.

--- src/api/vm.coffee
+++ src/api/vm.coffee
@@ -440,7 +440,7 @@

     if resourceSet?
       yield @allocateLimitsInResourceSet({
-        cpus: VM.CPUs.number - CPUs
+        cpus: CPUs - VM.CPUs.number
       }, resourceSet)
     if $isVMRunning VM
       if CPUs > VM.CPUs.max


fix(vm.create): don't require view perm on VM template

--- src/api/vm.coffee
+++ src/api/vm.coffee
@@ -257,7 +257,7 @@
 }

 create.resolve = {
-  template: ['template', 'VM-template'],
+  template: ['template', 'VM-template', ''],
 }

 exports.create = create


Add Spec T004-004 for LabelCategory::Models::LabelCategory#get_label_text()

--- spec/src/coffee/label_category/models/t004_label_category_spec.coffee
+++ spec/src/coffee/label_category/models/t004_label_category_spec.coffee
@@ -89,5 +89,41 @@
         @label.destroy()
         should.strictEqual @root.get("label"), undefined

+  context "004: get_label_text()", ->
+    beforeEach ->
+      @root = new @LabelCategory.Models.LabelCategory()
+      @fake_label =
+        set:  sinon.spy()
+        on:   sinon.spy()
+
+    context "001: A/B/C/D/E/F/G", ->
+      beforeEach ->
+        @root.parse_labels_recursive_func "A/B/C/D/E/F/G", @fake_label
+
+      it "001: simple", ->
+        @root.get_label_text().should.equal ""
+        @root.get("childrens")["A"].get_label_text().should.equal "A"
+        @root.get("childrens")["A"].get("childrens")["B"].get_label_text().should.equal "A/B"
+        @root.get("childrens")["A"].get("childrens")["B"].get("childrens")["C"].get_label_text().should.equal "A/B/C"
+
+      it "002: use parent", ->
+        @root
+          .get("childrens")["A"]
+          .get("childrens")["B"]
+          .get("childrens")["C"]
+          .get("childrens")["D"]
+          .get("parent")
+          .get_label_text().should.equal "A/B/C"
+        @root
+          .get("childrens")["A"]
+          .get("childrens")["B"]
+          .get("childrens")["C"]
+          .get("childrens")["D"]
+          .get("parent")
+          .get("childrens")["D"]
+          .get("childrens")["E"]
+          .get("childrens")["F"]
+          .get("childrens")["G"]
+          .get_label_text().should.equal "A/B/C/D/E/F/G"


:art:

:art:

Also, remove the failed update from the array if a subsequent try
successfully updates it.

--- lib/package-updates-status-view.coffee
+++ lib/package-updates-status-view.coffee
@@ -13,26 +13,15 @@
     @updatingPackages = []
     @failedUpdates = []

-    packageManager.on 'package-updated theme-updated', ({error, pack}) => @onDidUpdatePackage(pack)
     packageManager.on 'package-update-available theme-update-available', ({error, pack}) => @onPackageUpdateAvailable(pack)
     packageManager.on 'package-updating theme-updating', ({error, pack}) => @onPackageUpdating(pack)
+    packageManager.on 'package-updated theme-updated', ({error, pack}) => @onPackageUpdated(pack)
     packageManager.on 'package-update-failed theme-update-failed', ({error, pack}) => @onPackageUpdateFailed(pack)

     @updateTile()

     @on 'click', ->
       atom.commands.dispatch(atom.views.getView(atom.workspace), 'settings-view:check-for-package-updates')
-
-  onDidUpdatePackage: (pack) ->
-    for index, update of @updates
-      if update.name is pack.name
-        @updates.splice(index, 1)
-
-    for index, update of @updatingPackages
-      if update.name is pack.name
-        @updatingPackages.splice(index, 1)
-
-    @updateTile()

   onPackageUpdateAvailable: (pack) ->
     for update in @updates
@@ -44,6 +33,21 @@

   onPackageUpdating: (pack) ->
     @updatingPackages.push(pack)
+    @updateTile()
+
+  onPackageUpdated: (pack) ->
+    for index, update of @updates
+      if update.name is pack.name
+        @updates.splice(index, 1)
+
+    for index, update of @updatingPackages
+      if update.name is pack.name
+        @updatingPackages.splice(index, 1)
+
+    for index, update in @failedUpdates
+      if update.name is pack.name
+        @failedUpdates.splice(index, 1)
+
     @updateTile()

   onPackageUpdateFailed: (pack) ->


JSSegmentedControl deleted

JSSegmentedControl deleted

--- JSKit/04_JSSegmentedControl.coffee
+++ JSKit/04_JSSegmentedControl.coffee
@@ -1,35 +0,0 @@
-#*****************************************
-# JSSegmentedControl - radio switch parts class
-# Coded by kouichi.sakazaki 2013.11.05
-#*****************************************
-
-class JSSegmentedControl extends JSControl
-	constructor:(@_dataarray)->
-		super(JSRectMake(0, 0, 120, 32))
-		@_bgColor = JSColor("clearColor")
-		@_selectedSegmentIndex = -1
-
-	setValue:(@_selectedSegmentIndex)->
-		if ($(@_viewSelector).length)
-			$("input:radio[name='"+@_objectID+"_radio'][value='"+@_selectedSegmentIndex+"']").attr("checked", "checke")
-			$(@_viewSelector+"_radio").buttonset('refresh')
-
-	viewDidAppear:->
-		super()
-		if (!@_dataarray?)
-			return
-
-		tag = '
'
-		for i in [0...@_dataarray.length]
-			tag += '<input type="radio" id="'+@_objectID+'_radio_'+i+'" name="'+@_objectID+'_radio" value="'+i+'" />'+@_dataarray[i]+''
-		tag += '
'
-
-		if ($(@_viewSelector+"_radio").length)
-			$(@_viewSelector+"_radio").remove()
-		$(@_viewSelector).append(tag)
-		$(@_viewSelector+"_radio").buttonset().click(=>
-			@_selectedSegmentIndex = $("input[name='"+@_objectID+"_radio']:checked").val()
-			if (@action?)
-				@action(@_self)
-		)
-		@setValue(@_selectedSegmentIndex)


adding picture provider

adding picture provider

--- server/startup/avatar.coffee
+++ server/startup/avatar.coffee
@@ -44,10 +44,11 @@

 		if not file?

-			if Meteor.settings.public.sandstorm
-				if sandstormPictureUrl = RocketChat.models.Users.findOneByUsername(params.username.replace('.jpg', '')).services.sandstorm.picture?
-					console.log "Should redirect to: ", sandstormPictureUrl
-					res.setHeader 'Location', sandstormPictureUrl
+			if Meteor.settings?.public?.sandstorm
+				user = RocketChat.models.Users.findOneByUsername(params.username.replace('.jpg', ''))
+				if user?.services?.sandstorm?.picture
+					console.log "Should redirect to: ", user.services.sandstorm.picture
+					res.setHeader 'Location', user.services.sandstorm.picture
 					res.writeHead 302
 					res.end()
 					return


More whitespace :(

More whitespace :(

--- src/batman.coffee
+++ src/batman.coffee
@@ -66,8 +66,8 @@
 #   B) accept a callback as a second function application.
 # This is useful so that multiline functions can be passed as callbacks
 # without the need for wrapping brackets (which a CoffeeScript bug
-# requires them to have). `$block` also takes an optional function airity
-# argument as the first argument. If a `length` argument is given, and `length`
+# requires them to have). `$block` also takes an optional function airity
+# argument as the first argument. If a `length` argument is given, and `length`
 # or more arguments are passed, `$block` will call the second argument
 # (the function) with the passed arguments, regardless of their type.
 # Example:
@@ -248,7 +248,7 @@
     if @depth is 1 then super else @terminalProperty()?.getValue()
   setValue: (val) -> if @depth is 1 then super else @terminalProperty()?.setValue(val)
   unsetValue: -> if @depth is 1 then super else @terminalProperty()?.unsetValue()
-
+
 # Observable
 # ----------

@@ -603,7 +603,7 @@
     else
       @_batman.keyAccessors ||= new Batman.SimpleHash
       @_batman.keyAccessors.set(key, accessor) for key in keys
-
+
   @accessor: -> @classAccessor.apply @prototype, arguments
   accessor: @classAccessor

@@ -1089,7 +1089,6 @@
 # Models
 # ------

-
 class Batman.Model extends Batman.Object

   # ## Model API
@@ -1114,11 +1113,11 @@
   @find: (id) ->
     for record in @get('all').toArray()
       return record if record._id() is id
-
+
     record = new @(''+id)
     setTimeout (-> record.load()), 0
     record
-
+
   # Override this property if your model is indexed by a key other than `id`
   @id: 'id'

@@ -1490,7 +1489,7 @@
         for key of data
           data = data[key]
           break
-
+
         record.fromJSON data
         callback()

@@ -1673,7 +1672,7 @@
   # A beastly regular expression for pulling keypaths out of the JSON arguments to a filter.
   # It makes the following matches:
   #
-  # + `foo` and `baz.qux` in `foo, "bar", baz.qux`
+  # + `foo` and `baz.qux` in `foo, "bar", baz.qux`
   # + `foo.bar.baz` in `true, false, "true", "false", foo.bar.baz`
   # + `true.bar` in `2, true.bar`
   # + `truesay` in truesay
@@ -1683,17 +1682,17 @@
     \s*               # Be insensitive to whitespace between the comma and the actual arguments.
     (?!               # Use a lookahead to ensure we aren't matching true or false:
       (?:true|false)  # Match either true or false ...
-      \s*             # and make sure that there's nothing else that comes after the true or false ...
+      \s*             # and make sure that there's nothing else that comes after the true or false ...
       (?:$|,)         # before the end of this argument in the list.
     )
     ([a-zA-Z][\w\.]*) # Now that true and false can't be matched, match a dot delimited list of keys.
     \s*               # Be insensitive to whitespace before the next comma or end of the filter arguments list.
     (?:$|,)           # Match either the next comma or the end of the filter arguments list.
     ///
-
+
   # The `binding` which calculates the final result by reducing the initial value through all the filters.
   @accessor 'binding'
-    get: ->
+    get: ->
       @filterFunctions.reduce (value, fn, i) =>
         # Get any argument keypaths from the context stored at parse time.
         args = @filterArguments[i].map (argument) ->
@@ -1710,14 +1709,14 @@

     # Pull out the key and filter from the `@keyPath`.
     @parseFilter()
-
-    # If we're working with an `@key` and not an `@value`, find the context the key belongs to so we can
+
+    # If we're working with an `@key` and not an `@value`, find the context the key belongs to so we can
     # hold a reference to it for passing to the `dataChange` and `nodeChange` observers.
     if @key
       [unfilteredValue, @keyContext] = @renderContext.findKey @key

     shouldSet = yes
-
+
     if Batman.DOM.nodeIsEditable(@node)
       Batman.DOM.events.change @node, ->
         shouldSet = no
@@ -1727,7 +1726,7 @@
           if @key
             @keyContext.set @key, @node.value
         shouldSet = yes
-
+
     # Observe the value of this binding's `binding` and fire it immediately to update the node.
     @observe 'binding', yes, (value) ->
       if shouldSet
@@ -1741,8 +1740,8 @@
     # filter to) in these arrays.
     @filterFunctions = []
     @filterArguments = []
-
-    # Split the string by pipes to see if there are any filters.
+
+    # Split the string by pipes to see if there are any filters.
     filters = @keyPath.replace(/'/g, '"').split(/(?!")\s+\|\s+(?!")/)

     # The key will is always the first token before the pipe.
@@ -1780,8 +1779,8 @@
         if argument._keypath
           [_, argument.context] = @renderContext.findKey argument._keypath
         argument
-
-  # Turn a piece of a `data` keypath into a usable javascript object.
+
+  # Turn a piece of a `data` keypath into a usable javascript object.
   #  + replacing keypaths using the above regular expression
   #  + wrapping the `,` delimited list in square brackets
   #  + and `JSON.parse`ing them as an array.
@@ -1790,19 +1789,19 @@

 # The Render context class manages the stack of contexts accessible to a view during rendering.
 class RenderContext
-  constructor: (contexts...) ->
+  constructor: (contexts...) ->
     @contexts = contexts
     @storage = new Batman.Object
     @contexts.push @storage
-
+
   findKey: (key) ->
     base = key.split('.')[0]
     i = @contexts.length
     while i--
       context = @contexts[i]
-      if context.get?
+      if context.get?
         val = context.get(key)
-      else
+      else
         val = context[base]
       return [val, context] if val?
     return [container.get(key), container]
@@ -1839,7 +1838,7 @@
       node: node
       dataChange: dataChange
       nodeChange: nodeChange
-
+
 Batman.DOM = {
   # `Batman.DOM.readers` contains the functions used for binding a node's value or innerHTML, showing/hiding nodes,
   # and any other `data-#{name}=""` style DOM directives.
@@ -1934,7 +1933,7 @@
       object = new Batman.Object
       object[contextName] = context.get(key)
       context.push object
-
+
       node.onParseExit = ->
         context.pop()

@@ -1979,7 +1978,7 @@
       , 0

       nodeMap = new Batman.Hash
-
+
       collection = context.get key

       if collection?.observe
@@ -1993,12 +1992,12 @@
           iteratorContext[iteratorName] = item
           localClone.push iteratorContext
           localClone.push item
-
+
           renderer = new Batman.Renderer newNode, ->
             parent.insertBefore newNode, sibling
             parentRenderer.allow 'ready'
           , localClone
-
+
         collection.observe 'remove', remove = (item) ->
           oldNode = nodeMap.get item
           oldNode?.parentNode?.removeChild oldNode
@@ -2128,7 +2127,7 @@

 # Filters
 # -------
-filters = Batman.Filters =
+filters = Batman.Filters =
   truncate: (value, length, end = "...") ->
     if value.length > length
       value = value.substr(0, length-end.length) + end


fail early if the error occurs at the client level

--- test/helpers.coffee
+++ test/helpers.coffee
@@ -72,13 +72,12 @@
     store = if context? then context else {}

     callbackFactory = (done) -> (error, response, body) =>
-        store.error = error
+        throw error if(error)
         store.response = response
         store.body = body
         done()

     clean = ->
-        store.error = null
         store.response = null
         store.body = null


Equation builder, equals sign replaces operators Fixes #4713610

--- math/expression_components_spec.coffee
+++ math/expression_components_spec.coffee
@@ -20,6 +20,7 @@
       @comp.isVariable()
       @comp.isFraction()
       @comp.isExponentiation()
+      @comp.isRoot()

 describe "Expression Components", ->
   beforeEach ->


Remove console.log calls

Remove console.log calls

--- js/inner/build.coffee
+++ js/inner/build.coffee
@@ -504,9 +504,7 @@
       @fillActions(json.step, json.index)

       # Only append the output if it's for the current container
-      console.log("json.index:" + json.index + " current_container:" + @current_container().container_index)
       if @current_container().container_index == json.index
-        console.log("Appending output")
         @containers()[json.index].actions()[json.step].append_output([json.out])
     else
       # adds output to the action


Add config option for using fixed view on preview endpoint.

The view can be specified by setting the preview.view config option. An
example is shown below:

    preview:
        view:
            columns:[2]

In the above example, all calls to the preview endpoint will use a view
composed of only the concept with ID 2. This is an example taken from
varify to use only the sample column in calls to the preview endpoint.

Signed-off-by: Don Naegely <e690a32c1e2176a2bfface09e204830e1b5491e3@gmail.com>

--- src/coffee/cilantro/models/results.coffee
+++ src/coffee/cilantro/models/results.coffee
@@ -52,6 +52,11 @@
             @_refresh()

         fetch: (options={}) =>
+            if c.config.get('preview.view')?
+                options.type = 'POST'
+                options.contentType = 'application/json'
+                options.data = JSON.stringify({view: c.config.get('preview.view')})
+
             if @isDirty and @isWorkspaceOpen
                 # Since we are making the fetch call immediately below, the
                 # data will be synced again to the current view/context to


partial benchmarker

partial benchmarker

--- benchmark.coffee
+++ benchmark.coffee
@@ -11,10 +11,12 @@
 class Benchmark extends Testify.Turtle

   constructor: (args...) ->
+    @results = {}
     super(args...)

   measure: (name, work) ->
     @child(name, work)
+

   run: (options, callback) ->
     {iterations} = options
@@ -22,63 +24,68 @@
     results = {}

     suite_start = microtime.now()
-    @emitter.once "all_done", (results) =>
+    @emitter.on "all_done", (results) =>
       finish_time = microtime.now()
       out =
         runtime: finish_time - suite_start
-        data: {}
+        data: data = {}
       for name, values of results
         data[name] = new Dataset(values)
-      callback(out)
+      if callback
+        callback(out)

     iterate = =>
-      if ++count < iterations
-        @_run(results)
+      if ++count <= iterations
+        console.log count
+        @_run()
       else
-        @emitter.emit "all_done"
+        @emitter.emit "all_done", @results

-    @emitter.on "done", iterate
+    @emitter.on "COMPLETE", =>
+      @event "reset"
+      iterate()
     iterate()

   turtle_run: (args...) ->
     @work(@)
-    if @work.length == 0
-      @sync(args...)
+    @event "end"
+
+  _run: ->
+    @record_start(@name, -microtime.now())
+    @emitter.once "COMPLETE", =>
+      finish_time = microtime.now()
+      @record_end(@name, finish_time)
+    super()
+
+  record_start: (name, value) ->
+    if @parent
+      @parent.record_start(name, value)
     else
-      @async(args...)
+      console.log "start:", name, value
+      array = (@results[name] ||= [])
+      array.push(value)

-  _run: (results) ->
-    array = (results[@name] ||= [])
-    array.push(-microtime.now())
-    super(results)
-
-    #@work(@)
-    #if @work.length == 0
-      #@sync(args...)
-    #else
-      #@async(args...)
-
-    #else
-      #x = 0
-      #for child in @children
-        #child.once "done", =>
-          #if ++x = @children.length
-            #@done(results)
-        #child.one_run(results)
+  record_end: (name, value) ->
+    if @parent
+      @parent.record_end(name, value)
+    else
+      console.log "finish:", name, value
+      array = (@results[name] ||= [])
+      index = array.length - 1
+      array[index] = array[index] + value

   finish: ->
-    finish_time = microtime.now()
-    # do something with time
-    #@done()
+    #finish_time = microtime.now()
+    #@record_end(@name, finish_time)
+    @event "async_done"

-  done: (results) ->
-    finish_time = microtime.now()
-    times = results[@name]
-    index = times.length - 1
-    # the start time was added as a negative timestamp
-    times[index] = times[index] + finish_time
-    @emitter.emit "done", results
+  #done: (results) ->
+    #finish_time = microtime.now()
+    #times = results[@name]
+    #index = times.length - 1
+    ## the start time was added as a negative timestamp
+    #times[index] = times[index] + finish_time

 class Dataset


add : space

add : space

--- views/components/main/parts/task-panel.cjsx
+++ views/components/main/parts/task-panel.cjsx
@@ -208,7 +208,7 @@
           for i in [0..5]

               <OverlayTrigger placement='left' overlay={<Tooltip>{@state.tasks[i].name}
{@state.tasks[i].content}</Tooltip>}>
-                {@state.tasks[i].name}
+                {@state.tasks[i].name}
               </OverlayTrigger>

                 {@state.tasks[i].progress}


Adds dont_build to Build

Adds dont_build to Build

--- js/inner.coffee
+++ js/inner.coffee
@@ -205,6 +205,7 @@
     status: null
     failed: null
     infrastructure_fail: null
+    dont_build: null
     name: null
     branch: "unknown"
     previous: null


Validate linter results and refactor EditorLinter::lintResults

--- lib/editor-linter.coffee
+++ lib/editor-linter.coffee
@@ -1,4 +1,14 @@
 {CompositeDisposable, Emitter} = require 'atom'
+
+validateResults = (results) ->
+  unless results instanceof Array
+    throw new Error("Invalid linter response. found typeof " + (typeof results))
+
+  for r in results
+    unless r.type?
+      throw new Error('Missing "type". found keys', Object.keys(r))
+
+  return results

 class EditorLinter
   constructor: (@linter, @editor) ->
@@ -31,36 +41,27 @@
       console.error arguments[0].stack
       @progress onChange, false
   lintResults: (onChange, scopes) ->
-    promises = []
-    @linter.linters.forEach (linter) =>
+    return @linter.linters.map (linter) =>
       return if onChange and not linter.lintOnFly
       return if (not onChange) and linter.lintOnFly
       return unless (scopes.filter (entry) -> linter.scopes.indexOf(entry) isnt -1 ).length
-      promises.push(
-        (
-          new Promise (resolve) =>
-            retVal = linter.lint(@editor, @buffer)
-            if retVal instanceof Promise
-              retVal.then (results) =>
-                if results instanceof Array
-                  if linter.scope is 'project' then @linter.messagesProject.set linter, results
-                  else @messages.set linter, results
-                resolve()
-              .catch (error) =>
-                if linter.scope is 'project' then @linter.messagesProject.delete linter
-                else @messages.delete linter
-                atom.notifications.addError "#{error.message}", {detail: error.stack, dismissable: true}
-                resolve()
-            else
-              if retVal instanceof Array
-                if linter.scope is 'project' then @linter.messagesProject.set linter, retVal
-                else @messages.set linter, retVal
-              resolve()
-        ).then =>
-          @emitter.emit 'did-update'
-          @linter.view.render() if @editor is @linter.activeEditor
+
+      return new Promise((resolve) =>
+        # Using this callback style instead of `Promise.resolve` means we'll
+        # catch any exceptions thrown by `linter.lint`
+        resolve(linter.lint(@editor, @buffer))
+      ).then(validateResults)
+      .then((results) =>
+        if linter.scope is 'project' then @linter.messagesProject.set linter, results
+        else @messages.set linter, results
+      ).catch((error) =>
+        if linter.scope is 'project' then @linter.messagesProject.delete linter
+        else @messages.delete linter
+        atom.notifications.addError "#{error.message}", {detail: error.stack, dismissable: true}
+      ).then(=> # finally
+        @emitter.emit 'did-update'
+        @linter.view.render() if @editor is @linter.activeEditor
       )
-    promises

   progress: (onChange, newValue) ->
     if typeof newValue is 'undefined'


better result scrolling

better result scrolling

--- lib/editor/result.coffee
+++ lib/editor/result.coffee
@@ -60,9 +60,14 @@
         @disposables.add atom.config.observe 'editor.lineHeight', (h) =>
           @view.style.top = -h + 'em';
       when 'block'  then @view.classList.add 'under'
-    # @view.style.pointerEvents = 'auto'
-    @view.addEventListener 'mousewheel', (e) ->
-      e.stopPropagation()
+    @view.addEventListener 'mousewheel', (e) =>
+      if (@view.offsetHeight < @view.scrollHeight  ||
+          @view.offsetWidth  < @view.scrollWidth)  &&
+         ((e.deltaY > 0 && @view.scrollHeight - @view.scrollTop > @view.clientHeight) ||
+          (e.deltaY < 0 && @view.scrollTop > 0) ||
+          (e.deltaX > 0 && @view.scrollWidth - @view.scrollLeft > @view.clientWidth) ||
+          (e.deltaX < 0 && @view.scrollLeft > 0))
+        e.stopPropagation()
     # clicking on it will bring the current result to the top of the stack
     @view.addEventListener 'click', =>
       @view.parentNode.parentNode.appendChild @view.parentNode


ComputeUtils: add Softlayer to supported providers

--- workers/social/lib/social/models/computeproviders/computeutils.coffee
+++ workers/social/lib/social/models/computeproviders/computeutils.coffee
@@ -4,6 +4,7 @@
 PROVIDERS      =
   aws          : require './aws'
   koding       : require './koding'
+  softlayer    : require './softlayer' # remove this line to disable softlayer ~ GG
   rackspace    : require './rackspace'
   digitalocean : require './digitalocean'
   azure        : require './azure'


New monsters

New monsters


make error notifications dismissable

make error notifications dismissable

--- lib/flex-tool-bar.coffee
+++ lib/flex-tool-bar.coffee
@@ -79,11 +79,21 @@
 '''
       try
         fs.writeFileSync @configFilePath, defaultConfig
-        atom.notifications.addInfo 'We created a Tool Bar config file for you...', detail: @configFilePath
+        atom.notifications.addInfo 'We created a Tool Bar config file for you...', {
+          detail: @configFilePath
+          dismissable: true
+          buttons: [{
+            text: 'Edit Config'
+            onDidClick: => atom.workspace.open @configFilePath
+          }]
+        }
         return true
       catch err
         @configFilePath = null
-        atom.notifications.addError 'Something went wrong creating the Tool Bar config file! Please restart Atom to try again.'
+        atom.notifications.addError 'Something went wrong creating the Tool Bar config file! Please restart Atom to try again.', {
+          detail: err.stack
+          dismissable: true
+        }
         console.error err
         return false

@@ -168,7 +178,7 @@
       @unfixToolBarHeight()
     catch error
       @unfixToolBarHeight()
-      atom.notifications.addError "Could not load your toolbar from `#{fs.tildify(@configFilePath)}`"
+      atom.notifications.addError "Could not load your toolbar from `#{fs.tildify(@configFilePath)}`", dismissable: true
       throw error

   fixToolBarHeight: ->


fix js code error (#1956) (#1958)

fix js code error (#1956) (#1958)

* fix js code error

* use text in

* use text in httpBadRequest

--- BackofficeBundle/Resources/public/coffee/extendView/submitAdmin.coffee
+++ BackofficeBundle/Resources/public/coffee/extendView/submitAdmin.coffee
@@ -8,7 +8,7 @@
     window.OpenOrchestra.FormBehavior.channel.trigger 'deactivate', @, form

     new viewClass(@addOption(
-      html: response[0]
+      html: response
       submitted: true
     ))


Don't write after end

Don't write after end

--- src/sailthru.coffee
+++ src/sailthru.coffee
@@ -91,8 +91,8 @@
                     callback error.message, json_err
         req.on 'error', (err) ->
             callback err.message, err
+        req.write url.format({query: options.query}).replace('?', ''), 'utf8' if method is 'POST'
         req.end()
-        req.write url.format({query: options.query}).replace('?', ''), 'utf8' if method is 'POST'

     _api_request: (uri, data, request_method, callback, binary_data_params = []) ->
         return @_http_request uri, data, request_method, callback, binary_data_params