:art: Fix spec descriptions

:art: Fix spec descriptions

--- spec/autocomplete-manager-integration-spec.coffee
+++ spec/autocomplete-manager-integration-spec.coffee
@@ -679,7 +679,7 @@
             expect(newWidth).toBeGreaterThan 0
             expect(newWidth).toBeLessThan listWidth

-    describe "when number of useCoreMovementCommands is toggled", ->
+    describe "when useCoreMovementCommands is toggled", ->
       [suggestionList] = []

       beforeEach ->
@@ -707,7 +707,7 @@
         atom.commands.dispatch(suggestionList, 'core:move-down')
         expect(editorView.querySelectorAll('.autocomplete-plus li')[3]).toHaveClass 'selected'

-    describe "when number of useCoreMovementCommands is false", ->
+    describe "when useCoreMovementCommands is false", ->
       [suggestionList] = []

       beforeEach ->


Change sessions sign out spec because it reloads the page

--- spec/javascripts/integration/sessions_spec.coffee
+++ spec/javascripts/integration/sessions_spec.coffee
@@ -62,7 +62,7 @@
           equal find('.notification').text(), 'Invalid email or password.'

   describe 'sign out', ->
-    it 'sets isAuthenticated as false', ->
+    it 'has a sign out button', ->
       expect(1)
       authenticateSession()

@@ -71,6 +71,4 @@
       visit '/'

       andThen ->
-        click('header .user-sign-out')
-      andThen ->
-        equal(Dashboard.__container__.lookup('simple-auth-session:main').isAuthenticated, false)
+        equal find('header .user-sign-out').length,  1


fix searching for group set by id

fix searching for group set by id

--- src/app/common/services/group-service.coffee
+++ src/app/common/services/group-service.coffee
@@ -20,7 +20,7 @@
     task.definition.group_set?

   groupService.groupSetName = (id, unit) ->
-    gs = _.find(unit.group_sets, (gs) -> gs.id is id)
+    gs = _.find(unit.group_sets, (gs) -> gs.id is parseInt(id))
     if gs then gs.name else "Individual Work"

   groupService


Flexible vertical pseudoelement

Flexible vertical pseudoelement

--- app/assets/javascripts/activeadmin_ancestry_view/base.coffee
+++ app/assets/javascripts/activeadmin_ancestry_view/base.coffee
@@ -1,4 +1,42 @@
 $(document).on 'ready page:load turbolinks:load', ->
+  # get css rule as js object. Useful for changing css rules
+  getCSSRule = (ruleName, deleteFlag) ->
+    ruleName = ruleName.toLowerCase()
+    if document.styleSheets
+      i = 0
+      while i < document.styleSheets.length
+        styleSheet = document.styleSheets[i]
+        ii = 0
+        cssRule = false
+        loop
+          if styleSheet.cssRules
+            cssRule = styleSheet.cssRules[ii]
+          else
+            cssRule = styleSheet.rules[ii]
+          if cssRule
+            if cssRule.selectorText.toLowerCase() == ruleName
+              if deleteFlag == 'delete'
+                if styleSheet.cssRules
+                  styleSheet.deleteRule ii
+                else
+                  styleSheet.removeRule ii
+                return true
+              else
+                return cssRule
+          ii++
+          unless cssRule
+            break
+        i++
+    false
+
+  # add css rule. Useful for adding pseudoelements
+  addCSSRule = (ruleName, properies) ->
+    if document.styleSheets
+      if !getCSSRule(ruleName)
+        if document.styleSheets[0].addRule
+          document.styleSheets[0].addRule ruleName, properies, 0
+        else
+          document.styleSheets[0].insertRule ruleName + " { #{properies} }", 0
   findPanelHeader = (object) ->
     object.find('.panel').find('.panel-header')

@@ -7,6 +45,13 @@
     $('.panel-header').each ->
       if $(this).hasClass('selectable')
         $(this).removeClass('selectable')
+
+  changePseudoHeight = (node, oldHeight, pseudoElement) ->
+    additionalVal = $(node).height() - oldHeight
+    currentHeight = parseInt pseudoElement.style.height.replace('px','')
+    purposeHeight = (currentHeight + additionalVal).toString()
+
+    pseudoElement.style.height = purposeHeight.concat('px')

   # inherit color from parent panel on load
   # if parent has no color, inherit from parent of parent
@@ -20,18 +65,19 @@

   # show-hide single div
   $('.show-content').click ->
+    node    = $(this).parents('.panel-container')
     content = $(this).parent().next('.panel_contents')
+
+    oldNodeHeight = $(node).height()
+    verticalLine  = getCSSRule('[id="' + $(node).attr('id') + '"]::before')
+
     if content.is(':hidden')
-      content.show('fast')
+      content.show 'fast', ->
+        changePseudoHeight(node, oldNodeHeight, verticalLine)

-      nodeId = $(this).parents('.panel-container').attr('id')
-      console.log document.styleSheets[0].cssRules[0]
-
-      # console.log verticalLine
-      # verticalLine = getCSSRule("[id='#{nodeId}']::before")
-      # verticalLine.style.height = '100px'
     else
-      content.hide('fast')
+      content.hide 'fast', ->
+        changePseudoHeight(node, oldNodeHeight, verticalLine)

   # show-hide nodes
   $('.show-childrens').click ->
@@ -61,24 +107,25 @@

   #--- Tree branches ---

-  # find middle of node
+  # find middle of node (px)
   middleOfHeight = (node) ->
     Math.abs $(node).height() / 2

   distanceToTop = (node, target) ->
     Math.abs $(node).offset().top - $(target).offset().top

-  # find distance btw node and its last child
+  # find distance btw node and its last child (px)
   verticalBranchDist = (node, lastChild) ->
     distanceToTop(node, lastChild) + middleOfHeight(node)

   baseBranchProp =
+    "transition: 0.2s; " +
     "content: ''; " +
     "position: absolute; " +
     "border: 0.1em solid gray; "

   # vertical line properies with dynamic height
-  veticalBranchProp = (id, height) ->
+  veticalBranchProp = (height) ->
     "margin-left: 2em; " +
     "height: #{height}px; " +
     "z-index: -1; " +
@@ -93,72 +140,33 @@
     baseBranchProp

   # add vertical line ( :before pseudoelement) to panel which has children
-  addVerticalLine = (node) ->
-    id        = $(node).attr 'id'
-    lastChild = $(node).parent().find ".panel-container[data-last-child=#{id}]"
+  addVerticalLine = (node, purposeNode) ->
+    distance = verticalBranchDist(node, purposeNode)
+    id       = $(node).attr('id')

-    if $(lastChild).length
-      distance = verticalBranchDist(node, lastChild)
-      document.styleSheets[0].addRule(
-        "[id='#{id}']::before",
-        "#{veticalBranchProp(id, distance)}"
-        )
+    addCSSRule(
+      "[id='#{id}']::before",
+      veticalBranchProp(distance)
+      )

   # add horizontal line (:after pseudoelement) to all panels except root
   addHorizontalLine = (node) ->
-    if $(node).hasClass('panel-root')
+    id = $(node).attr('id')
+    height = middleOfHeight(node)
+    addCSSRule(
+      "[id='#{id}']::after",
+      horizontalBranchProp(height)
+      )
+
+  $('.panel-parent').each ->
+    nodeId    = $(this).attr('id')
+    lastChild = $(this).parent().find(
+      ".panel-container[data-last-child=#{nodeId}]")
+
+    addVerticalLine(this, lastChild) if $(lastChild).length
+
+  $('.panel-container').each ->
+    if $(this).hasClass('panel-root')
       true
     else
-      id = $(node).attr('id')
-      height = middleOfHeight(node)
-      document.styleSheets[0].addRule(
-        "[id='#{id}']::after",
-        "#{horizontalBranchProp(height)}"
-        )
-
-  $('.panel-parent').each ->
-    addVerticalLine(this)
-
-  $('.panel-container').each ->
-    addHorizontalLine(this)
-
-  getCSSRule = (ruleName, deleteFlag) ->
-    ruleName = ruleName.toLowerCase()
-    if document.styleSheets
-      i = 0
-      while i < document.styleSheets.length
-        styleSheet = document.styleSheets[i]
-        ii = 0
-        cssRule = false
-        loop
-          if styleSheet.cssRules
-            cssRule = styleSheet.cssRules[ii]
-          else
-            cssRule = styleSheet.rules[ii]
-          if cssRule
-            if cssRule.selectorText.toLowerCase() == ruleName
-              if deleteFlag == 'delete'
-                if styleSheet.cssRules
-                  styleSheet.deleteRule ii
-                else
-                  styleSheet.removeRule ii
-                return true
-              else
-                return cssRule
-          ii++
-          unless cssRule
-            break
-        i++
-    false
-
-  killCSSRule = (ruleName) ->
-    getCSSRule ruleName, 'delete'
-
-  addCSSRule = (ruleName) ->
-    if document.styleSheets
-      if !getCSSRule(ruleName)
-        if document.styleSheets[0].addRule
-          document.styleSheets[0].addRule ruleName, null, 0
-        else
-          document.styleSheets[0].insertRule ruleName + ' { }', 0
-    getCSSRule ruleName+      addHorizontalLine(this)


Use select2 for data_type select

Use select2 for data_type select

--- app/assets/javascripts/admin/views/parameters/edit.js.coffee
+++ app/assets/javascripts/admin/views/parameters/edit.js.coffee
@@ -13,6 +13,7 @@
     Backbone.Validation.bind @

     @$('#parameter-data-type').val @model.get('data_type')
+    @$('#parameter-data-type').select2()

     $('#content-header').find('.page-title').text(if @model.isNew() then 'New Parameter' else 'Edit Parameter')


Always throw back error even if there is an error loading the flash for example translating the error message

--- app/assets/javascripts/darkswarm/services/checkout.js.coffee
+++ app/assets/javascripts/darkswarm/services/checkout.js.coffee
@@ -21,8 +21,10 @@
         try
           @handle_checkout_error_response(response)
         catch error
-          @loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error
-          throw error # generate a BugsnagJS alert
+          try
+            @loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error
+          finally
+            throw error # generate a BugsnagJS alert

     handle_checkout_error_response: (response) =>
       if response.data.path


OX-236 cloudify fixed

OX-236 cloudify fixed

--- app/assets/javascripts/level_creator/plugins/cloudify.coffee
+++ app/assets/javascripts/level_creator/plugins/cloudify.coffee
@@ -5,7 +5,7 @@

 class Cloudify

-  DESCRIPTION : "Makes clouds out of the given input"
+  DESCRIPTION : "Makes colored clouds out of the given input"

   PARAMETER :
     input :
@@ -25,7 +25,7 @@
     @cloud.onload = => @ready = true

-  execute : ({ input : { rgba, dimensions }}) ->
+  execute : ({ input : { rgba, dimensions }, r, g, b, a}) ->

     { cloud, ready, size } = @

@@ -40,26 +40,23 @@
     canvas.height = height

     context = canvas.getContext("2d")
+
+    for h in [0...height] by size*0.3
+      for w in [0...width] by size*0.3

-    i = 0
-    j = 0
-    while i < 50 and j < 1000
-      j++
-      x = Math.floor(Math.random() * width)
-      y = Math.floor(Math.random() * height)
+        x = w + Math.floor(Math.random() * size - size*0.5)
+        y = h + Math.floor(Math.random() * size - size*0.5)

-      a = rgba[(y * width + x) * 4 + 3]
-
-      if a is 0
-        continue
-
-      context.drawImage(cloud, x - size*0.5, y - size*0.5)
-      i++
+        testA = rgba[(y * width + x) * 4 + 3]
+
+        if testA isnt 0
+          context.drawImage(cloud, x - size*0.5, y - size*0.5)

     canvasData = context.getImageData(0, 0, width, height).data
     for l in [0...canvasData.length] by 4
-      rgba[l + 0] = 0
-      rgba[l + 1] = 0
-      rgba[l + 2] = 0
-      rgba[l + 3] = canvasData[l + 3]
+      ao = canvasData[l + 3]
+      rgba[l + 0] = r
+      rgba[l + 1] = g
+      rgba[l + 2] = b
+      rgba[l + 3] = ao * a


Fix JS error

Fix JS error

--- app/assets/javascripts/views/game_instructions_screen.coffee
+++ app/assets/javascripts/views/game_instructions_screen.coffee
@@ -7,4 +7,4 @@
   render: ->
     super
     @$el.text('Game instructions go here')
-    setTimeout(-> gameView.goto(new InitialCountdownScreen)), 5000+    setTimeout (-> gameView.goto(new InitialCountdownScreen)), 5000


Using arrowed line only if it connects to not first parent.

It is easy to see which branch is merged.

--- app/assets/javascripts/branch-graph.js.coffee
+++ app/assets/javascripts/branch-graph.js.coffee
@@ -191,57 +191,58 @@

   drawLines: (x, y, commit) ->
     r = @r
-    for parent in commit.parents
+    for parent, i in commit.parents
       parentCommit = @preparedCommits[parent[0]]
       parentY = @offsetY + @unitTime * parentCommit.time
       parentX1 = @offsetX + @unitSpace * (@mspace - parentCommit.space)
       parentX2 = @offsetX + @unitSpace * (@mspace - parent[1])

-      if parentCommit.space is commit.space and parentCommit.space is parent[1]
-        r.path(["M", x, y, "L", parentX1, parentY]).attr(
-          stroke: @colors[parentCommit.space]
-          "stroke-width": 2
+      # Set line color
+      if parentCommit.space <= commit.space
+        color = @colors[commit.space]
+
+      else
+        color = @colors[parentCommit.space]
+
+      # Build line shape
+      if parent[1] is commit.space
+        d1 = [0, 5]
+        d2 = [0, 10]
+        arrow = "l-2,5,4,0,-2,-5"
+
+      else if parent[1] < commit.space
+        d1 = [3, 3]
+        d2 = [7, 5]
+        arrow = "l5,0,-2,4,-3,-4"
+
+      else
+        d1 = [-3, 3]
+        d2 = [-7, 5]
+        arrow = "l-5,0,2,4,3,-4"
+
+      # Start point
+      route = ["M", x + d1[0], y + d1[1]]
+
+      # Add arrow if not first parent
+      if i > 0
+        route.push(arrow)
+
+      # Circumvent if overlap
+      if commit.space isnt parentCommit.space or commit.space isnt parent[1]
+        route.push(
+          "L", x + d2[0], y + d2[1],
+          "L", parentX2, y + 10,
+          "L", parentX2, parentY - 5,
         )

-      else if parentCommit.space < commit.space
-        if x is parentX2
-          r
-            .path([
-              "M", x, y + 5,
-              "l-2,5,4,0,-2,-5",
-              "L", x, y + 10,
-              "L", parentX2, y + 10,
-              "L", parentX2, parentY - 5,
-              "L", parentX1, parentY])
-            .attr(
-              stroke: @colors[commit.space]
-              "stroke-width": 2)
-
-        else
-          r
-            .path([
-              "M", x + 3, y + 3,
-              "l5,0,-2,4,-3,-4",
-              "L", x + 7, y + 5,
-              "L", parentX2, y + 10,
-              "L", parentX2, parentY - 5,
-              "L", parentX1, parentY])
-            .attr(
-              stroke: @colors[commit.space]
-              "stroke-width": 2)
-
-      else
-        r
-          .path([
-            "M", x - 3, y + 3,
-            "l-5,0,2,4,3,-4",
-            "L", x - 7, y + 5,
-            "L", parentX2, y + 10,
-            "L", parentX2, parentY - 5,
-            "L", parentX1, parentY])
-          .attr(
-            stroke: @colors[parentCommit.space]
-            "stroke-width": 2)
+      # End point
+      route.push("L", parentX1, parentY)
+
+      r
+        .path(route)
+        .attr(
+          stroke: color
+          "stroke-width": 2)

   markCommit: (x, y, commit, graphHeight) ->
     if commit.id is @options.commit_id


Swap lines so overlay gets displayed after

--- app/assets/javascripts/flow_manager.js.coffee
+++ app/assets/javascripts/flow_manager.js.coffee
@@ -3,8 +3,8 @@

   displayChangeOverlay: (e) ->
     e.preventDefault()
+    React.renderComponent ChooseFlowManagerColumn(), document.getElementById('overlay')
     $('#overlay').show()
-    React.renderComponent ChooseFlowManagerColumn(), document.getElementById('overlay')

   render: ->
     {ul, div, section, img, h2, span, li, a, section} = React.DOM


Fix javascript error when showing the same help message twice

--- app/assets/javascripts/modules/help.js.coffee
+++ app/assets/javascripts/modules/help.js.coffee
@@ -226,6 +226,7 @@
       $tip.find('[data-role=next]').show().toggleClass('disabled', index == queue.length - 1)

   showCurrent = ->
+    console.log queue.length, queue[index]
     if queue[index].wait
       wait(showCurrentImmediate)
     else if queue[index].waitOnAnimate
@@ -250,8 +251,9 @@
   add = (key, options={}) ->
     unless tourRunning
       options = $.extend({}, defaultHelpOptions, tourOptions[key], options, key: key)
-      queue.push(options) unless options.once && shown[key]
-      showCurrent()
+      unless options.once && shown[key]
+        queue.push(options)
+        showCurrent()

   current = ->
     if tourRunning then nil else queue[index]


BaseStackTemplatesView: use options instead

--- client/stacks/lib/views/stacks/basestacktemplatesview.coffee
+++ client/stacks/lib/views/stacks/basestacktemplatesview.coffee
@@ -46,7 +46,7 @@

     onboardingView.on 'StackOnboardingCompleted', (template) =>
       onboardingView.destroy()
-      @showEditor template, no, yes
+      @showEditor { inEditMode: no, showHelpContent: yes }, template

     onboardingView.on 'ScrollTo', (direction = 'top') =>
       duration = 500
@@ -91,15 +91,17 @@

       remote.api.JStackTemplate.one { _id: stackTemplate }, (err, template) =>
         if not (showError err) and template
-        then @showEditor template, inEditMode = yes
+        then @showEditor { inEditMode: yes }, template
         else
           showError 'Stack Template not found!'
           @setRoute()
     else
-      @showEditor stackTemplate, inEditMode = yes
+      @showEditor { inEditMode: yes }, stackTemplate

-  showEditor: (stackTemplate, inEditMode, showHelpContent) ->
+  showEditor: (options, stackTemplate) ->
+
+    { inEditMode, showHelpContent } = options

     @initialView.hide()


No need anymore to reset before fetching

--- core/app/backbone/collections/ndp_evidence_collection.coffee
+++ core/app/backbone/collections/ndp_evidence_collection.coffee
@@ -10,7 +10,6 @@

     @_wheel = @fact.getFactWheel()
     @_wheel.on 'sync', =>
-      @reset []
       @fetch()

   comparator: (item) -> - item.get('impact')


sidebar: channel deleted event handler method of sidebar message item

--- client/Social/Activity/sidebar/messageitem.coffee
+++ client/Social/Activity/sidebar/messageitem.coffee
@@ -10,13 +10,18 @@

     super options, data

+    data.on 'ChannelDeleted', @bound 'channelDeleted'
+
     @icon = new SidebarMessageItemIcon {}, data
     @text = new SidebarMessageItemText {}, data

-    data.on 'ChannelDeleted', =>
-      if location.pathname is "/Activity/Message/#{ data.getId() }"
-        KD.singletons.router.clear()
-      @getDelegate().removeItem this
+  channelDeleted: ->
+
+    if location.pathname is "/#{@getOption 'route'}"
+      KD.singletons.router.clear()
+
+    @getDelegate().removeItem this
+

   pistachio: ->
     "{{> @icon}}{{> @text}}{{> @unreadCount}}"


ComputeController: update state of local stack instance once it started to build

--- client/app/lib/providers/computecontroller.coffee
+++ client/app/lib/providers/computecontroller.coffee
@@ -677,12 +677,15 @@

       machine.getBaseKite( createIfNotExists = no ).disconnect()

-    call = @getKloud().buildStack { stackId: stack._id }
+    stackId = stack._id
+    call    = @getKloud().buildStack { stackId }

     .then (res) =>

+      (@findStackFromStackId stackId)?.status.state = 'Building'
+
       kd.log "build stack res:", res
-      @eventListener.addListener 'apply', stack._id
+      @eventListener.addListener 'apply', stackId

     .timeout globals.COMPUTECONTROLLER_TIMEOUT


Made newly created visualization profile get selected by default

--- community/server/src/main/coffeescript/neo4j/webadmin/modules/databrowser/visualization/views/VisualizationProfileView.coffee
+++ community/server/src/main/coffeescript/neo4j/webadmin/modules/databrowser/visualization/views/VisualizationProfileView.coffee
@@ -39,6 +39,7 @@
       initialize : (opts) =>

         @profiles = opts.dataBrowserSettings.getVisualizationProfiles()
+        @settings = opts.dataBrowserSettings
         @styleViews = []

       save : () =>
@@ -57,6 +58,7 @@
         @_updateRuleOrderFromUI()
         if @isInCreateMode
           @profiles.add @profile
+          @settings.setCurrentVisualizationProfile(@profile.id)
         @profile.save()

         window.location = '#/data/'


Cycle the cyclones. Closes #51

Cycle the cyclones. Closes #51


update builder specs

update builder specs

--- test/components/task-plan/builder.spec.coffee
+++ test/components/task-plan/builder.spec.coffee
@@ -14,9 +14,10 @@
 TutorDateFormat = TimeStore.getFormat()
 ISO_DATE_FORMAT = 'YYYY-MM-DD'

-yesterday = (new Date(Date.now() - 1000 * 3600 * 24)).toString()
-tomorrow = (new Date(Date.now() + 1000 * 3600 * 24)).toString()
-dayAfter = (new Date(Date.now() + 1000 * 3600 * 48)).toString()
+twoDaysBefore = moment(TimeStore.getNow()).subtract(2, 'days').format(ISO_DATE_FORMAT)
+yesterday = moment(TimeStore.getNow()).subtract(1, 'day').format(ISO_DATE_FORMAT)
+tomorrow = moment(TimeStore.getNow()).add(1, 'day').format(ISO_DATE_FORMAT)
+dayAfter = moment(TimeStore.getNow()).add(2, 'day').format(ISO_DATE_FORMAT)

 getDateString = (value) -> TimeHelper.getMomentPreserveDate(value).format(TutorDateFormat)
 getISODateString = (value) -> TimeHelper.getMomentPreserveDate(value).format(ISO_DATE_FORMAT)
@@ -27,7 +28,7 @@
   id: '1'
   title: 'hello',
   description: 'description',
-  published_at: yesterday}, {opens_at: yesterday, due_at: yesterday, target_id: COURSES[0].periods[0].id})
+  published_at: twoDaysBefore}, {opens_at: twoDaysBefore, due_at: yesterday, target_id: COURSES[0].periods[0].id})

 helper = (model, routerQuery) -> PlanRenderHelper(model, Builder, {}, {}, routerQuery)

@@ -106,8 +107,8 @@
       element.setIndividualPeriods()

       #set due dates to be different
-      element.setDueAt(getDateString(tomorrow), firstPeriod)
-      element.setDueAt(getDateString(dayAfter), secondPeriod)
+      element.setDueAt(getISODateString(tomorrow), firstPeriod)
+      element.setDueAt(getISODateString(dayAfter), secondPeriod)

       #set all periods
       element.setAllPeriods()
@@ -125,39 +126,39 @@
       element.setIndividualPeriods()

       #set due dates to be different
-      element.setDueAt(getDateString(tomorrow), firstPeriod)
-      element.setDueAt(getDateString(dayAfter), secondPeriod)
+      element.setDueAt(getISODateString(tomorrow), firstPeriod)
+      element.setDueAt(getISODateString(dayAfter), secondPeriod)

       #set all periods
       element.setAllPeriods()

       #due at should reset to query string due at
       dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
-      expect(getDateString(dueAt)).to.be.equal(getDateString(dayAfter))
+      expect(getISODateString(dueAt)).to.be.equal(getISODateString(dayAfter))

   it 'can update open date with date obj', ->
     helper(NEW_READING).then ({dom, element}) ->
-      element.setOpensAt(new Date(dayAfter))
+      element.setOpensAt(getISODateString(dayAfter))
       opensAt = TaskPlanStore.getOpensAt(NEW_READING.id)
-      expect(getDateString(opensAt)).to.be.equal(getDateString(dayAfter))
+      expect(getISODateString(opensAt)).to.be.equal(getISODateString(dayAfter))

   it 'can update open date with string', ->
     helper(NEW_READING).then ({dom, element}) ->
-      element.setOpensAt(getDateString(tomorrow))
+      element.setOpensAt(getISODateString(tomorrow))
       opensAt = TaskPlanStore.getOpensAt(NEW_READING.id)
-      expect(getDateString(opensAt)).to.be.equal(getDateString(tomorrow))
+      expect(getISODateString(opensAt)).to.be.equal(getISODateString(tomorrow))

   it 'can update due date with date obj', ->
     helper(NEW_READING).then ({dom, element}) ->
-      element.setDueAt(new Date(dayAfter))
-      dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
-      expect(getDateString(dueAt)).to.be.equal(getDateString(dayAfter))
+      element.setDueAt(getISODateString(dayAfter))
+      dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
+      expect(getISODateString(dueAt)).to.be.equal(getISODateString(dayAfter))

   it 'can update due date with string', ->
     helper(NEW_READING).then ({dom, element}) ->
-      element.setDueAt(getDateString(tomorrow))
-      dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
-      expect(getDateString(dueAt)).to.be.equal(getDateString(tomorrow))
+      element.setDueAt(getISODateString(tomorrow))
+      dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
+      expect(getISODateString(dueAt)).to.be.equal(getISODateString(tomorrow))

   it 'can disable individual periods', ->
     disabledPeriod = COURSES[0].periods[1]
@@ -184,13 +185,13 @@

       fakePeriodDisable(element, disabledPeriod)
       fakePeriodDisable(element, anotherDisabledPeriod)
-      element.setOpensAt(new Date(dayAfter), period)
+      element.setOpensAt(getISODateString(dayAfter), period)

       opensAt = TaskPlanStore.getOpensAt(NEW_READING.id)
       expect(opensAt).to.not.be.ok

       opensAt = TaskPlanStore.getOpensAt(NEW_READING.id, period.id)
-      expect(getDateString(opensAt)).to.be.equal(getDateString(dayAfter))
+      expect(getISODateString(opensAt)).to.be.equal(getISODateString(dayAfter))

   it 'can update due date for individual period', ->
     period = COURSES[0].periods[0]
@@ -201,14 +202,14 @@
       element.setIndividualPeriods()

       fakePeriodDisable(element, disabledPeriod)
-      element.setDueAt(new Date(dayAfter), anotherPeriod)
-      element.setDueAt(new Date(tomorrow), period)
+      element.setDueAt(getISODateString(dayAfter), anotherPeriod)
+      element.setDueAt(getISODateString(tomorrow), period)

       dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
       expect(dueAt).to.not.be.ok

       dueAt = TaskPlanStore.getDueAt(NEW_READING.id, period.id)
-      expect(getDateString(dueAt)).to.be.equal(getDateString(tomorrow))
+      expect(getISODateString(dueAt)).to.be.equal(getISODateString(tomorrow))

   it 'sets the correct moment timezone on mount', ->
     courseId = COURSES[0].periods[0].id
@@ -223,6 +224,6 @@
   it 'sets the default due date when based on query string', ->
     helper(NEW_READING, {due_at: getISODateString(dayAfter)} ).then ({dom, element}) ->
       dueAt = TaskPlanStore.getDueAt(NEW_READING.id)
-      expect(getDateString(dueAt)).to.be.equal(getDateString(dayAfter))
+      expect(getISODateString(dueAt)).to.be.equal(getISODateString(dayAfter))
       expect(dom.querySelector('.-assignment-due-date .datepicker__input-container input').value)
         .to.be.equal(getDateString(dayAfter))


navigation: 'NavigationWorkspaceItem::setUnreadCount'

--- client/Main/navigation/navigationworkspaceitem.coffee
+++ client/Main/navigation/navigationworkspaceitem.coffee
@@ -52,6 +52,19 @@
     new WorkspaceSettingsPopup { position, delegate: navItem }

+  setUnreadCount: (unreadCount = 0) ->
+
+    @count = unreadCount
+
+    if unreadCount is 0
+      @unreadCount.hide()
+      @unsetClass 'unread'
+    else
+      @unreadCount.updatePartial unreadCount
+      @unreadCount.show()
+      @setClass 'unread'
+
+
   pistachio: ->
     """
     <figure></figure>


Sidebar: Fixed broken machine state getter after merge.

--- client/Social/Activity/sidebar/activitysidebar.coffee
+++ client/Social/Activity/sidebar/activitysidebar.coffee
@@ -416,7 +416,7 @@

       KD.utils.stopDOMEvent event
       KD.singletons.mainView.openMachineModal machine, machineItem
-
+
     else if event.target.nodeName is 'CITE' and machineItem.type is 'machine'

       @handleMachineToggle machineItem, event
@@ -425,9 +425,9 @@

       return

-    else if machineItem.machine.status.state is Machine.State.Building
-
-      return
+    else if machineItem.getData().status.state is Machine.State.Building
+
+      return

   handleMachineToggle: (machineItem, event) ->


removed forsaken method NewCommentForm::commentPosted

--- client/app/CommonViews/comments/newcommentform.coffee
+++ client/app/CommonViews/comments/newcommentform.coffee
@@ -45,10 +45,6 @@
     @commentInput.on "focus", =>
       @getDelegate().emit "commentInputReceivedFocus"

-  commentPosted:->
-    @commentInput.setValue ""
-    @resetCommentField()
-
   makeCommentFieldActive:->
     @getDelegate().emit "commentInputReceivedFocus"
     (KD.getSingleton "windowController").setKeyView @commentInput


[social][feed] updated following feed and public feed queries with security, code readability and correct where query

--- client/landing/app/MainApp/sidebar/sidebarview.coffee
+++ client/landing/app/MainApp/sidebar/sidebarview.coffee
@@ -264,39 +264,22 @@
   navItems =
     # temp until groups are implemented
     do ->
-      if location.hostname is "koding.com"
-        id        : "navigation"
-        title     : "navigation"
-        items     : [
-          { title : "Home",           path : "/Activity" }
-          { title : "Activity",       path : "/Activity" }
-          { title : "Topics",         path : "/Topics" }
-          { title : "Members",        path : "/Members" }
-          { title : "Develop",        path : "/Develop", loggedIn: yes }
-          { title : "Apps",           path : "/Apps" }
-          { type  : "separator" }
-          { title : "Invite Friends", type : "account", loggedIn: yes }
-          { title : "Account",        path : "/Account", type : "account", loggedIn  : yes }
-          { title : "Logout",         path : "/Logout",  type : "account", loggedIn  : yes }
-          { title : "Login",          path : "/Login",   type : "account", loggedOut : yes }
-        ]
-      else
-        id        : "navigation"
-        title     : "navigation"
-        items     : [
-          { title : "Home",           path : "/Activity" }
-          { title : "Activity",       path : "/Activity" }
-          { title : "Topics",         path : "/Topics" }
-          { title : "Members",        path : "/Members" }
-          { title : "Groups",         path : "/Groups" }
-          { title : "Develop",        path : "/Develop",  loggedIn: yes }
-          { title : "Apps",           path : "/Apps" }
-          { type  : "separator" }
-          { title : "Invite Friends", type : "account", loggedIn: yes }
-          { title : "Account",        path : "/Account", type : "account", loggedIn  : yes }
-          { title : "Logout",         path : "/Logout",  type : "account", loggedIn  : yes }
-          { title : "Login",          path : "/Login",   type : "account", loggedOut : yes }
-        ]
+      id        : "navigation"
+      title     : "navigation"
+      items     : [
+        { title : "Home",           path : "/Activity" }
+        { title : "Activity",       path : "/Activity" }
+        { title : "Topics",         path : "/Topics" }
+        { title : "Members",        path : "/Members" }
+        { title : "Groups",         path : "/Groups" }
+        { title : "Develop",        path : "/Develop",  loggedIn: yes }
+        { title : "Apps",           path : "/Apps" }
+        { type  : "separator" }
+        { title : "Invite Friends", type : "account", loggedIn: yes }
+        { title : "Account",        path : "/Account", type : "account", loggedIn  : yes }
+        { title : "Logout",         path : "/Logout",  type : "account", loggedIn  : yes }
+        { title : "Login",          path : "/Login",   type : "account", loggedOut : yes }
+      ]

   bottomControlsItems =
     id : "finder-bottom-controls"


only restrict public access when necessary

--- salvus/page/project.coffee
+++ salvus/page/project.coffee
@@ -3445,7 +3445,7 @@

         ext = filename_extension(opts.path)

-        if not public_access_supported(opts.path)
+        if @public_access and not public_access_supported(opts.path)
             @file_action_dialog
                 fullname : opts.path
                 isdir    : false


Added source to hull example

Added source to hull example

--- examples/convexHull/hull2d.coffee
+++ examples/convexHull/hull2d.coffee
@@ -1,13 +1,18 @@
+# based on Wikipedia http://en.wikipedia.org/wiki/QuickHull
+
 pex = require('../../build/pex')

 { Rect, Vec2, Edge, Line2D, Triangle2D } = pex.geom
 { MathUtils } = pex.utils

+sigstep = 1
+
+
 #TODO: cleanup remove resultA, increasedDises etc
 pex.sys.Window.create
   settings:
-    width: 1280
-    height: 720
+    width: 640 * 0.75
+    height: 1136 * 0.75
     type: '2d'
   points: []
   edges: []


Add comment.

Add comment.

--- common/lib/xmodule/xmodule/js/src/problem/edit.coffee
+++ common/lib/xmodule/xmodule/js/src/problem/edit.coffee
@@ -234,6 +234,7 @@
             floatValue = parseFloat(answersList[0]);

         if(!isNaN(floatValue)) {
+          // Tries to extract parameters from string like 'expr +- tolerance'
           var params = /(.*?)\+\-\s*(.*?$)/.exec(answersList[0]),
               answer = answersList[0].replace(/\s+/g, '');
           if(params) {


Nodejs Web Server Tests: add generateCsrfCookie helper and use it in generateRequestParamsEncodeBody function

--- servers/testhelper/index.coffee
+++ servers/testhelper/index.coffee
@@ -109,6 +109,11 @@
   if requestParams.body
     requestParams.body = querystring.stringify requestParams.body

+  if params.csrfCookie
+    cookie             = generateCsrfTokenCookie()
+    requestParams.jar ?= request.jar()
+    requestParams.jar.setCookie cookie, requestParams.url
+
   return requestParams

@@ -126,6 +131,15 @@
       target[prop] = source[prop]

   return target
+
+
+generateCsrfTokenCookie = (csrfToken = null) ->
+
+  csrfToken ?= generateRandomString()
+  cookie     = request.cookie "_csrf=#{csrfToken}"
+
+  return cookie
+

 convertToArray = (commaSeparatedData = '') ->


remove useless info

remove useless info

--- client/landing/app/Applications/Account.kdapplication/account/accSettingsDevKodingKeys.coffee
+++ client/landing/app/Applications/Account.kdapplication/account/accSettingsDevKodingKeys.coffee
@@ -93,5 +93,4 @@
   partial:(data)->
     """
       #{data.hostname or "Unknown Host"}
-      #{data.key}
     """


Corrected a socket issue, using the wrong case identifier attribute name

--- src/main/client/grid/grid-directives-tables.coffee
+++ src/main/client/grid/grid-directives-tables.coffee
@@ -223,19 +223,17 @@
             ## value. Note that the value is never transmitted over the socket.

             scope.$on 'socket:field', (evt, original) ->
-              console.log "Got socket:field", evt, original

               ## If we get a cell editing event, we need to identify the cell element, and then update
               ## the right stuff. We might need to do something similar for a row, too.

               if handsonTable != undefined and original.data.userNumber > 0
-                handleEditCell original.data.parameters.case, original.data.parameters.field, original.data.editingClasses
+                handleEditCell original.data.parameters.case_id, original.data.parameters.field, original.data.editingClasses

             scope.$on 'socket:record', (evt, original) ->
-              console.log "Got socket:record", evt, original
               if handsonTable != undefined and original.data.userNumber > 0
-                handleAddRecord original.data.parameters.case, original.data.editingClasses
+                handleAddRecord original.data.parameters.case_id, original.data.editingClasses

             ## Needs to find the case identifier, which requires a bit of poking around


removed color from classnames

removed color from classnames

--- plugins/image.coffee
+++ plugins/image.coffee
@@ -248,16 +248,16 @@

                     switch position
                         when "left"
-                            overlay.big.addClass("blueOverlayLeft").removeClass("blueOverlayRight").css(left: third).show()
+                            overlay.big.addClass("bigOverlayLeft").removeClass("bigOverlayRight").css(left: third).show()
                             overlay.left.hide()
                             overlay.right.hide()
                         when "middle"
-                            overlay.big.removeClass "blueOverlayLeft blueOverlayRight"
+                            overlay.big.removeClass "bigOverlayLeft bigOverlayRight"
                             overlay.big.hide()
                             overlay.left.show()
                             overlay.right.show()
                         when "right"
-                            overlay.big.addClass("blueOverlayRight").removeClass("blueOverlayLeft").css(left: 0).show()
+                            overlay.big.addClass("bigOverlayRight").removeClass("bigOverlayLeft").css(left: 0).show()
                             overlay.left.hide()
                             overlay.right.hide()
                         else
@@ -357,7 +357,7 @@
                 handleLeaveEvent: (event, ui) ->
                     func = ->
                         $(ui.helper).append($('

'))
-                        $('.bigBlueOverlay, .smallDottedOverlay').remove()
+                        $('.bigOverlay, .smallOverlay').remove()
                     window.timeoutTrash = setTimeout(func , 300)
                     helper.removeTmpNodes()

@@ -419,12 +419,12 @@
                 height: editable.height()

             overlay =
-                big: $("
").addClass("bigBlueOverlay").css(
+                big: $("
").addClass("bigOverlay").css(
                   width: third * 2
                   height: editable.height()
                 )
-                left: $("
").addClass("smallDottedOverlay smallDottedOverlayLeft").css(overlayMiddleConfig)
-                right: $("
").addClass("smallDottedOverlay smallDottedOverlayRight").css(overlayMiddleConfig).css("left", third * 2)
+                left: $("
").addClass("smallOverlay smallOverlayLeft").css(overlayMiddleConfig)
+                right: $("
").addClass("smallOverlay smallOverlayRight").css(overlayMiddleConfig).css("left", third * 2)

             dnd.init()


disable highlighter plugin in master

disable highlighter plugin in master

--- plugins/plugins.cson
+++ plugins/plugins.cson
@@ -1,6 +1,6 @@
 # You may add the plugins that should be included here.
 plugins: [
-  'highlights'
+ # 'highlights'
  # 'example'
 ]


fix(e2e): stray pause removed

fix(e2e): stray pause removed

--- vue/tests/e2e/helpers/pageHelper.coffee
+++ vue/tests/e2e/helpers/pageHelper.coffee
@@ -28,7 +28,6 @@
   click: (selector, wait) ->
     @waitFor(selector, wait)
     test.click(selector)
-    test.pause(wait)

   scrollTo: (selector, callback, wait) ->
     @waitFor(selector, wait)


Fixed java/lang/runtime being overwritten with empty data, Doppio Compilation works

--- web/doppio-jvm/scripts/demo/doppio-api.coffee
+++ web/doppio-jvm/scripts/demo/doppio-api.coffee
@@ -2,6 +2,7 @@
 root = this

 # /home/doppio/vendor/classes/java/lang/Runtime.class - Causing magic number error as byte array is []
+# /home/doppio/vendor/classes/java/lang/Runtime.class

 root.init_editor = ->
     root.editor = ace.edit('source')
@@ -53,7 +54,9 @@
                 data = util.bytestr_to_array node.fs.readFileSync(fullpath)
             catch e
                 data = null
-            return cb(data) if data != null
+            if data != null and data.length <= 0
+                console.log "Empty data for: #{fullpath}"
+            return cb(data) if data != null and data.length > 0
         failure_cb(-> throw new Error "Error: No file found for class #{cls}.")

     load_mini_rt: ->
@@ -72,7 +75,11 @@
             [base, ext] = path.split '.'
             file_count++
             cls = base.substr base_dir.length
-            node.fs.writeFileSync(path, util.array_to_bytestr(file), 'utf8', true)
+            # if path == 'vendor/classes/java/lang/Runtime.class'
+            #     console.log "Writting runtime"
+            if file.length > 0
+                node.fs.writeFileSync(path, util.array_to_bytestr(file), 'utf8', true)
+            return
         untar new util.BytesArray(util.bytestr_to_array data), writeOneFile
         end_untar = (new Date()).getTime()
         console.log "Untarring took a total of #{end_untar-start_untar}ms."
@@ -110,19 +117,21 @@
     compile: (stdout, fname, finish_cb) ->
         console.log "Compiling #{fname} ..."
         start_compile = (new Date()).getTime()
-        jvm.set_classpath '/home/doppio/vendor/classes/', './:/home/doppio'
+        # jvm.set_classpath '/home/doppio/vendor/classes/', './:/home/doppio'
+        jvm.set_classpath '/home/doppio/vendor/classes/', './'
+
         user_input = (resume) -> resume ''
         bs_cl = new ClassLoader.BootstrapClassLoader(@read_classfile)
         rs = new runtime.RuntimeState(stdout, user_input, bs_cl)
         @rs = rs
         args = [ fname ]
-        my_cb = ->
+        my_cb = =>
             end_compile = (new Date()).getTime()
             @rs = null
             console.log "javac took a total of #{end_compile-start_compile}ms."
             console.log 'Compilation complete'
             finish_cb()
-        jvm.run_class rs, 'classes/util/Javac', args, my_cb
+        jvm.run_class(rs, 'classes/util/Javac', args, my_cb)
         return

     exec: (stdout, stdin, class_name, class_args, finish_cb) ->


removed logging

removed logging

--- web/doppio-jvm/scripts/demo/doppio-api.coffee
+++ web/doppio-jvm/scripts/demo/doppio-api.coffee
@@ -2,7 +2,6 @@
 root = this

 # /home/doppio/vendor/classes/java/lang/Runtime.class - Causing magic number error as byte array is []
-# /home/doppio/vendor/classes/java/lang/Runtime.class

 root.init_editor = ->
     root.editor = ace.edit('source')
@@ -54,8 +53,6 @@
                 data = util.bytestr_to_array node.fs.readFileSync(fullpath)
             catch e
                 data = null
-            if data != null and data.length <= 0
-                console.log "Empty data for: #{fullpath}"
             return cb(data) if data != null and data.length > 0
         failure_cb(-> throw new Error "Error: No file found for class #{cls}.")

@@ -75,8 +72,6 @@
             [base, ext] = path.split '.'
             file_count++
             cls = base.substr base_dir.length
-            # if path == 'vendor/classes/java/lang/Runtime.class'
-            #     console.log "Writting runtime"
             if file.length > 0
                 node.fs.writeFileSync(path, util.array_to_bytestr(file), 'utf8', true)
             return


moving initialize logic into _eventBus so views do not all have to explicitly call super


Automatically use default preferences

Automatically use default preferences

--- source/scripts/models/pref.coffee
+++ source/scripts/models/pref.coffee
@@ -9,9 +9,6 @@

   defaults:

-    # Default id
-    id: 0
-
     # Settings
     sort:          1 # 0: no, 1: yes
     night:         0 # 0: light, 1: dark, 2:auto
@@ -20,6 +17,17 @@
     dateFormat:    'dd/mm/yy'
     confirmDelete: 1 # 0: no, 1: yes
     moveCompleted: 1 # 0: instantly, 1: on app launch, 2: never
+
+  constructor: ->
+    super
+
+    @id = 0
+
+    # Replace null values with default ones
+    @on 'refresh', ->
+      for key, value of Pref::defaults
+        if this[key] is null
+          this[key] = value

 # Create a new instance of Setting
 prefs = new Pref()


Cleanup.

Cleanup.

--- spec/cachedTemplatesSpec.coffee
+++ spec/cachedTemplatesSpec.coffee
@@ -1,19 +1,16 @@
-if typeof module != 'undefined' && module.exports
-  require './spec_helper'
-  require '../src/transparency'
-
 describe "Transparency", ->

   it "cache templates", ->
-    doc = jQuery(
-     '

+    doc = $ """
+

-
')
+

+      """

     data = [
       hello: "Hello"
@@ -23,8 +20,8 @@
       world: "Canada!"
     ]

-    expected = jQuery(
-     '

+    expected = $ """
+

             Hello
@@ -35,7 +32,8 @@
             Canada!

-
')
+

+      """

     doc.find('.container').render(data)
     doc.find('.container').render(data)


Remove duplicated tests from AppEngineComponent

--- test/src/specs/app/Components/AppEngineComponentSpec.coffee
+++ test/src/specs/app/Components/AppEngineComponentSpec.coffee
@@ -3,30 +3,8 @@
 describe "AppEngineComponent Specs", ->
   AppEngineComponent = AppEngine.Components.AppEngineComponent

-  Behaviours.expectRequiredParameters(AppEngine.Components.AppEngineComponent, ["wrappedElement"])
-
-  describe "New AppEngineComponent", ->
-    it "should be an abstract class", ->
-      try
-        new AppEngineComponent()
-        expect("This should error").toEqual("here")
-      catch e
-        expect(e instanceof AppEngine.Helpers.Error).toBeTruthy()
-        expect(e.getRootError().message).toEqual("Unable to create instance of Abstract class 'AppEngineComponent'")
-
-    it "should fail without the correct parameters on creation", ->
-      class A extends AppEngineComponent
-      try
-        new A()
-        expect("This should error").toEqual("here")
-      catch e
-        expect(e instanceof AppEngine.Helpers.Error).toBeTruthy()
-        expect(e.getRootError().message).toEqual("The constructor expects the parameter 'el' to be passed in as a config parameter")
-
-    it "should create an object using the correct parameters", ->
-      class A extends AppEngineComponent
-      new A({el: "1", wrappedElement: "2"})
-
+  Behaviours.expectRequiredParameters(AppEngineComponent, ["wrappedElement"])
+  Behaviours.expectAbstract(AppEngineComponent)

   describe "Initialise", ->
     class A extends AppEngineComponent


This is a patch to correct a bug in Haiku's ability to update CloudFront distributions.

--- src/publish/bucket/cloudfront/distribution.coffee
+++ src/publish/bucket/cloudfront/distribution.coffee
@@ -209,6 +209,7 @@
       if deepEqual current, newconfig
         Distribution
       else
+        Distribution.DistributionConfig = newconfig
         updateDistribution ETag, Distribution


activity: rename instance property names of `CommentViewHeader` class

--- client/Social/Activity/views/comments/commentviewheader.coffee
+++ client/Social/Activity/views/comments/commentviewheader.coffee
@@ -2,15 +2,15 @@

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

-    options.cssClass          = KD.utils.curry "show-more-comments in", options.cssClass
-    options.maxCommentToShow ?= 3
+    options.cssClass  = KD.utils.curry "show-more-comments in", options.cssClass
+    options.maxCount ?= 3

     super options, data

-    {@maxCount}  = options
-    @oldCount    = data.repliesCount
-    @newCount    = 0
-    @onListCount = if data.repliesCount > @maxCommentToShow then @maxCommentToShow else data.repliesCount
+    {@maxCount}    = options
+    @previousCount = data.repliesCount
+    @currentCount  = 0
+    @listedCount = if data.repliesCount > @maxCount then @maxCount else data.repliesCount

     @allItemsLink = new CustomLinkView
       cssClass    : "all-count"
@@ -39,49 +39,49 @@

     # Get correct number of items in list from controller
     # I'm not sure maybe its not a good idea
-    @onListCount = @parent.commentController?.getItemCount?()
+    @listedCount = @parent.commentController?.getItemCount?()

     # If there are same number of comments in list with total
     # comment size means we don't need to show new item count
     @newItemsLink.unsetClass('in')

     # If its our comments so it's not a new comment
-    if @newCount > 0 then @newCount--
+    if @currentCount > 0 then @currentCount--

     @updateNewCount()

   ownCommentDeleted: ->

-    @newCount++  if @newCount > 0
+    @currentCount++  if @currentCount > 0

   update: ->

     # If there is no comments so we can not have new comments
-    if @oldCount is 0 then @newCount = 0
+    if @previousCount is 0 then @currentCount = 0

     # If we have comments more than 0 we should show the new item link
-    if @newCount > 0
+    if @currentCount > 0
       if @liveUpdate
         @emit "ListAll"
       else
         @setClass 'new'
         @allItemsLink.hide()
         @show()
-        @newItemsLink.updatePartial "#{ KD.utils.formatPlural @newCount, 'new comment' }..."
+        @newItemsLink.updatePartial "#{ KD.utils.formatPlural @currentCount, 'new comment' }..."
         @newItemsLink.setClass('in')
     else
       @unsetClass 'new'
       @newItemsLink.unsetClass('in')

-    if @onListCount > @oldCount
-      @onListCount = @oldCount
+    if @listedCount > @previousCount
+      @listedCount = @previousCount

-    if @onListCount is @getData().repliesCount
-      @newCount = 0
+    if @listedCount is @getData().repliesCount
+      @currentCount = 0

-    if @onListCount is @oldCount and @newCount is 0
+    if @listedCount is @previousCount and @currentCount is 0
       @hide()
     else
       @show()
@@ -90,8 +90,8 @@
   reset: ->

     @hide()
-    @newCount = 0
-    @onListCount = @getData().repliesCount
+    @currentCount = 0
+    @listedCount = @getData().repliesCount
     @update()

@@ -116,7 +116,7 @@
     {repliesCount} = @getData()

     repliesCount
-    unless repliesCount and repliesCount > @maxCommentToShow
+    unless repliesCount and repliesCount > @maxCount
       @hide()

@@ -125,26 +125,26 @@
     # Get correct number of items in list from controller
     # I'm not sure maybe its not a good idea
     if @parent?.commentController?.getItemCount?()
-      @onListCount = @parent.commentController.getItemCount()
-    _newCount = @getData().repliesCount
+      @listedCount = @parent.commentController.getItemCount()
+    _currentCount = @getData().repliesCount

     # Show View all bla bla link if there are more comments
-    # than maxCommentToShow
-    @show() if _newCount > @maxCommentToShow and @onListCount < _newCount
+    # than @maxCount
+    @show() if _currentCount > @maxCount and @listedCount < _currentCount

-    # Check the oldCount before update anything
+    # Check the previousCount before update anything
     # if its less means someone deleted a comment
     # otherwise it meanse we have a new comment
     # if nothing changed it means user clicked like button
     # so we don't need to touch anything
-    if _newCount > @oldCount
-      @newCount++
-    else if _newCount < @oldCount
-      if @newCount > 0 then @newCount--
+    if _currentCount > @previousCount
+      @currentCount++
+    else if _currentCount < @previousCount
+      if @currentCount > 0 then @currentCount--

     # If the count is changed then we need to update UI
-    if _newCount isnt @oldCount
-      @oldCount = _newCount
+    if _currentCount isnt @previousCount
+      @previousCount = _currentCount
       @utils.defer => @updateNewCount()

     super


Workspace: Removed dummy session key.

Workspace: Removed dummy session key.

--- client/app/CommonViews/workspace/collaborativeworkspace.coffee
+++ client/app/CommonViews/workspace/collaborativeworkspace.coffee
@@ -55,7 +55,6 @@
     callback()

   createSessionKey: ->
-    return "alexx:zota:82"
     nick = KD.nick()
     u    = KD.utils
     return  "#{nick}:#{u.generatePassword(4)}:#{u.getRandomNumber(100)}"


FinderTreeController: move/copy are instance level methods we need to use them as is.

[fixes #77048848]

--- client/finder/filetree/controllers/findertreecontroller.coffee
+++ client/finder/filetree/controllers/findertreecontroller.coffee
@@ -294,7 +294,7 @@
     movedNodes = []
     results = nodesToBeMoved.map (node) ->
       sourceItem = node.getData()
-      FSItem.move(sourceItem, targetItem).then ->
+      sourceItem.move("#{targetItem.path}/").then ->
         movedNodes.push node

     Promise.all(results).then =>
@@ -303,6 +303,7 @@
       @refreshFolder targetNodeView

     .catch (err) =>
+      warn "Move failed with error:", err
       @notify null, null, err

     .nodeify callback
@@ -317,14 +318,14 @@
     copiedNodes = []
     results = nodesToBeCopied.map (node) ->
       sourceItem = node.getData()
-      FSItem.copy(sourceItem, targetItem).then ->
+      sourceItem.copy(targetItem.path).then ->
         copiedNodes.push node

     Promise.all(results).then =>
       @notify "#{copiedNodes.length} item#{if copiedNodes.length > 1 then 's' else ''} copied!", "success"
-      @refreshFolder targetNodeView

     .catch (err) =>
+      warn "Copy failed with error:", err
       @notify null, null, err

     .nodeify callback


updated the URL for collab watch mode

updated the URL for collab watch mode

--- client/ide/lib/views/statusbar/idechatheadwatchitemview.coffee
+++ client/ide/lib/views/statusbar/idechatheadwatchitemview.coffee
@@ -21,7 +21,7 @@
     @addSubView @info = new CustomLinkView
       title        : ''
       cssClass     : 'info'
-      href         : 'http://learn.koding.com/collaboration#watch'
+      href         : 'http://learn.koding.com/guides/collaboration/#what-does-quot-watch-quot-mode-mean-'
       target       : '_blank'


fixes for IE

fixes for IE

Former-commit-id: f461b147993669a0216dea7d0b2c0e252290c516 [formerly bb5c8e693c312d8e3e1850d887b8bec8f964d887] [formerly bafa811e77df5f1b824f13463cf5f0fb520238a4 [formerly fc2433cd2ef3c99906528b7d4a855ce61ba39fd6]] [formerly e5c439af139d6fe3eeb64c5268edb814b85e3f2d [formerly 157299574417c719ff2fb40b47dec14bd9714ada] [formerly 017fe5dc44de2b773998e8ddbbfbea8d3bea37ff [formerly 017fe5dc44de2b773998e8ddbbfbea8d3bea37ff [formerly 01f9c028b27301f9a4ff0a3f8a2b9f8d80374409]]]]
Former-commit-id: a75feca7aff586f139dc2853a9661e9d73bb8d7e [formerly 1d95a713d2c2786e2eaef5fd7d68f6cad99c1d16] [formerly 92012ffa24826f19a953302216f1e8863ea0929d [formerly e1b1c962fda2276abdb6e16cc876f94fd445d322]]
Former-commit-id: 7418372413a0e291442f67ba33afc36acbc0347f [formerly e70974af42a1da296d70a4a8c3a99834fbba9b5d]
Former-commit-id: 990d980c4aa21f3ce57263e9cf8ffa2e6bfde275
Former-commit-id: b816a244d9f205e0e5f58c1cf4f3c87c6edfa488

--- @client/saas_landing_page.coffee
+++ @client/saas_landing_page.coffee
@@ -245,16 +245,20 @@
       style:
         position: 'relative'
         width: SAAS_PAGE_WIDTH - 1
-        height: 551
+        height: (SAAS_PAGE_WIDTH - 2) * 1080/1920 + 2

       VIDEO
         preload: "auto"
         loop: true
         autoPlay: false
-        width: SAAS_PAGE_WIDTH - 2
-        height: 551
         ref: "video"
         controls: true
+        style:
+          marginTop: 1
+          width: SAAS_PAGE_WIDTH - 2
+          height: (SAAS_PAGE_WIDTH - 2) * 1080/1920
+          borderRadius: 8
+

         SOURCE
           src: asset("saas_landing_page/#{VIDEO_FILE}.mp4")


don't show upload processor error if not logged in

--- server/allow_and_startup.coffee
+++ server/allow_and_startup.coffee
@@ -21,7 +21,7 @@
 Meteor.publish "binary_data", ->
   BinaryData.find {}  if @userId
 Meteor.publish "simple_upload_processor_status", ->
-  SimpleUploadProcessorStatus.find {} if @userId
+  SimpleUploadProcessorStatus.find {}

 # ----------------------------------------
 #   Upload processor status


Added test for future auto-propagation feature

--- spec/core/EventMessageSpec.coffee
+++ spec/core/EventMessageSpec.coffee
@@ -142,3 +142,21 @@
 			check = ->
 				msg.getRequired "doesntexist"
 			expect(check).toThrow("Variable \"doesntexist\" not found on message with address \"address\"")
+
+	# Planned feature.
+	xdescribe "auto-propagation", ->
+		it "should automatically propagate errors using replies when told to", ->
+			reply = sinon.spy()
+			msg = new EventMessage null, "errorpropagation", reply
+			error = new Error "test error"
+			# When inside a message handler, using `autoPropagate` should provide error aggregation.
+			msg.autoPropagate ->
+				throw error
+
+			waitsFor (-> reply.called), "Reply never called", 100
+			runs ->
+				expect(reply.callCount).toBe 1
+				call = reply.getCall 0
+				replyMsg = call.args[0]
+				expect(replyMsg.status).toBe "error"
+				expect(replyMsg.error).toBe error


Use cloned model for UserPopoverContentView to not run into trouble with urls for following/unfollowing

--- core/app/backbone/views/users/user_popover_content_view.coffee
+++ core/app/backbone/views/users/user_popover_content_view.coffee
@@ -20,4 +20,4 @@
       positioning: {align: 'left', side: 'bottom'}
       selector: options.selector || '.js-user-link'
       $offsetParent: options.$offsetParent
-      tooltipViewFactory: -> new UserPopoverContentView model: user
+      tooltipViewFactory: -> new UserPopoverContentView model: user.clone()


Test that when a compiler is registered after booting, it prints a message explaining that the compiler will only run for future fragments

--- spec/unpoly/syntax_spec.js.coffee
+++ spec/unpoly/syntax_spec.js.coffee
@@ -20,6 +20,12 @@
         expect(observeElement).not.toHaveBeenCalledWith($container[0])
         expect(observeElement).not.toHaveBeenCalledWith($otherChild[0])
         expect(observeElement).toHaveBeenCalledWith($child[0])
+
+      it 'prints a message when a compiler is registered after booting, explaining that the compiler will only run for future fragments', ->
+        spyOn(up, 'puts').and.callThrough()
+        up.compiler('.foo', u.noop)
+        expect(up.puts).toHaveBeenCalled()
+        expect(up.puts.calls.argsFor(0)[0]).toMatch(/will run for future fragments/i)

     describe 'up.$compiler', ->


Cleanup.

Cleanup.

--- app/assets/javascripts/voluntary_ranking/controllers/user/rankings/show_controller.js.coffee
+++ app/assets/javascripts/voluntary_ranking/controllers/user/rankings/show_controller.js.coffee
@@ -55,5 +55,12 @@
       @send('reload')

     reload: ->
-      @set('model', @store.find('user_ranking_item', user_id: VoluntaryOnEmberjs.User.current().id, adjective: @get('adjective'), negative_adjective: @get('negativeAdjective'), topic: @get('topic'), scope: @get('scope')))
+      @set(
+        'model',
+        @store.find(
+          'user_ranking_item',
+          user_id: VoluntaryOnEmberjs.User.current().id, adjective: @get('adjective'), negative_adjective: @get('negativeAdjective'),
+          topic: @get('topic'), scope: @get('scope')
+        )
+      )
 )


up the zoom level

up the zoom level

--- overrides.coffee
+++ overrides.coffee
@@ -132,7 +132,7 @@
       ), 1000
     , 500 # time that 'Nice Work' screen is displayed

-  @loadLatLong: -> $("#subject-coords").html("#{@roundTo(3, @lat)} N, #{@roundTo(3, @long)} W")
+  @loadLatLong: -> $("#subject-coords").html("#{@roundTo(3, @lat)} N, #{@roundTo(3, @long)} W")

   @nextImage: (queue = 2) ->
     # queue is 2 by default to load the image 2 ahead of subject into the offscreen-right position


[master] find_peer.coffee now handles WIDE data

--- tools/find_peer.coffee
+++ tools/find_peer.coffee
@@ -30,11 +30,11 @@
   lazy stream
     .lines
     .map(String)
-    .skip 5
     .map (str) ->
+      # Skip non entries
       if str[0] != '*'
         return
-      path = str.split(/\s+/)[4..-2]
+      path = str.trim()[61..].split(/\s+/)[..-2]
       if path.length < 2
         return
       for i in [0..path.length - 2]


interpret invalid filenames literarlly

interpret invalid filenames literarlly

--- app/pages/lab/subject-set.cjsx
+++ app/pages/lab/subject-set.cjsx
@@ -275,7 +275,7 @@
     filesInMetadata = []
     for key, value of metadata
       extensions = if isAdmin() then '\\.\\D\\w{2,4}' else "(?:#{'\\'.concat VALID_SUBJECT_EXTENSIONS.join '|\\'})"
-      filesInValue = value.match? ///([^#{INVALID_FILENAME_CHARS.join ''}]+#{extensions})///gi
+      filesInValue = value.match? ///([^#{INVALID_FILENAME_CHARS.join '\\'}]+#{extensions})///gi
       if filesInValue?
         filesInMetadata.push filesInValue...
     filesInMetadata


Fix class name check

Fix class name check


[grunt] disable autohint for `webfont` task and added temporary workaround for template bug

--- tasks/grunt-webfont.coffee
+++ tasks/grunt-webfont.coffee
@@ -14,6 +14,7 @@
         types: 'eot,woff,ttf'
         hashes: false # disabled, since all assets cache-busted by other Grunt task
         styles: ''
+        template: '' # temporary workaround for node v6 support (see path.extname docs)
         templateOptions:
           baseClass: 'icon'
           classPrefix: 'icon--'
@@ -21,5 +22,6 @@
         # @note Normalize may yeild different results for different engines
         #       https://github.com/sapegin/grunt-webfont/issues/222
         normalize: true
+        autoHint: false
         htmlDemo: false
         engine: 'node'


Add `menu_darwin.cson` Korean translation

--- def/ko/menu_darwin.cson
+++ def/ko/menu_darwin.cson
@@ -3,312 +3,312 @@
     value: "Atom"
     submenu:
       "About Atom":
-        value: "About Atom"
+        value: "Atom에 대하여"
       "View License":
-        value: "View License"
+        value: "라이센스 보기"
       "Preferences…":
-        value: "Preferences..."
+        value: "환경설정..."
       "Config…":
-        value: "Config..."
+        value: "구성..."
       "Init Script…":
-        value: "Init Script..."
+        value: "초기화 스크립트..."
       "Keymap…":
-        value: "Keymap..."
+        value: "단축키 맵핑..."
       "Snippets…":
-        value: "Snippets..."
+        value: "스닙..."
       "Stylesheet…":
-        value: "Stylesheet..."
+        value: "스타일시트..."
       "Install Shell Commands":
-        value: "Install Shell Commands"
+        value: "쉘 커맨드 설치"
       "Hide Atom":
-        value: "Hide Atom"
+        value: "Atom 숨기기"
       "Hide Others":
-        value: "Hide Others"
+        value: "다른 창 숨기기"
       "Show All":
-        value: "Show All"
+        value: "모두 보이기"
       Quit:
-        value: "Quit"
+        value: "종료"
   File:
-    value: "File"
+    value: "파일"
     submenu:
       "New Window":
-        value: "New Window"
+        value: "새 창"
       "New File":
-        value: "New File"
+        value: "새 파일"
       "Open…":
-        value: "Open..."
+        value: "열기..."
       "Add Project Folder…":
-        value: "Add Project Folder..."
+        value: "프로젝트 폴더 추가..."
       "Reopen Last Item":
-        value: "Reopen Last Item"
+        value: "마지막으로 닫은 파일 다시 열기"
       Save:
-        value: "Save"
+        value: "저장"
       "Save As…":
-        value: "Save As..."
+        value: "다른 이름으로 저장..."
       "Save All":
-        value: "Save All"
+        value: "모두 저장"
       "Close Tab":
-        value: "Close Tab"
+        value: "탭 닫기"
       "Close Pane":
-        value: "Close Pane"
+        value: "분할 창 닫기"
       "Close Window":
-        value: "Close Window"
+        value: "창 닫기"
       "Close All Tabs":
-        value: "Close All Tabs"
+        value: "모든 탭 닫기"
   Edit:
-    value: "Edit"
+    value: "편집"
     submenu:
       Undo:
-        value: "Undo"
+        value: "실행 취소"
       Redo:
-        value: "Redo"
+        value: "다시 실행"
       Cut:
-        value: "Cut"
+        value: "오려두기"
       Copy:
-        value: "Copy"
+        value: "복사"
       "Copy Path":
-        value: "Copy Path"
+        value: "경로 복사"
       Paste:
-        value: "Paste"
+        value: "붙이기"
       "Select All":
-        value: "Select All"
+        value: "모두 선택"
       "Toggle Comments":
-        value: "Toggle Comments"
+        value: "주석 토글"
       Lines:
-        value: "Lines"
+        value: "행"
         submenu:
           Indent:
-            value: "Indent"
+            value: "들여쓰기"
           Outdent:
-            value: "Outdent"
+            value: "내어쓰기"
           "Auto Indent":
-            value: "Auto Indent"
+            value: "자동 들여쓰기"
           "Move Line Up":
-            value: "Move Line Up"
+            value: "행 위로 이동"
           "Move Line Down":
-            value: "Move Line Down"
+            value: "행 아래로 이동"
           "Duplicate Lines":
-            value: "Duplicate Lines"
+            value: "행 복제"
           "Delete Line":
-            value: "Delete Line"
+            value: "행 삭제"
           "Join Lines":
-            value: "Join Lines"
+            value: "행 조인"
       Columns:
-        value: "Columns"
+        value: "열"
         submenu:
           "Move Selection Left":
-            value: "Move Selection Left"
+            value: "선택된 열 왼쪽으로 이동"
           "Move Selection Right":
-            value: "Move Selection Right"
+            value: "선택된 열 오른쪽으로 이동"
       Text:
-        value: "Text"
+        value: "문장"
         submenu:
           "Upper Case":
-            value: "Upper Case"
+            value: "대문자로 변환"
           "Lower Case":
-            value: "Lower Case"
+            value: "소문자로 변환"
           "Delete to End of Word":
-            value: "Delete to End of Word"
+            value: "마지막 단어 삭제"
           "Delete to Previous Word Boundary":
-            value: "Delete to Previous Word Boundary"
+            value: "이전 단어 경계 삭제"
           "Delete to Next Word Boundary":
-            value: "Delete to Next Word Boundary"
+            value: "다음 단어 경계 삭제"
           "Delete Line":
-            value: "Delete Line"
+            value: "행 삭제"
           Transpose:
-            value: "Transpose"
+            value: "치환"
       Folding:
-        value: "Folding"
+        value: "코드 폴딩"
         submenu:
           Fold:
-            value: "Fold"
+            value: "접기"
           Unfold:
-            value: "Unfold"
+            value: "풀기"
           "Unfold All":
-            value: "Unfold All"
+            value: "모두 풀기"
           "Fold All":
-            value: "Fold All"
+            value: "모두 접기"
           "Fold Level 1":
-            value: "Fold Level 1"
+            value: "접기 단계 1"
           "Fold Level 2":
-            value: "Fold Level 2"
+            value: "접기 단계 2"
           "Fold Level 3":
-            value: "Fold Level 3"
+            value: "접기 단계 3"
           "Fold Level 4":
-            value: "Fold Level 4"
+            value: "접기 단계 4"
           "Fold Level 5":
-            value: "Fold Level 5"
+            value: "접기 단계 5"
           "Fold Level 6":
-            value: "Fold Level 6"
+            value: "접기 단계 6"
           "Fold Level 7":
-            value: "Fold Level 7"
+            value: "접기 단계 7"
           "Fold Level 8":
-            value: "Fold Level 8"
+            value: "접기 단계 8"
           "Fold Level 9":
-            value: "Fold Level 9"
+            value: "접기 단계 9"
       "Reflow Selection":
-        value: "Reflow Selection"
+        value: "선택 재정렬"
       Bookmark:
-        value: "Bookmark"
+        value: "북마크"
         submenu:
           "View All":
-            value: "View All"
+            value: "모두 보이기"
           "Toggle Bookmark":
-            value: "Toggle Bookmark"
+            value: "북마크 토글"
           "Jump to Next Bookmark":
-            value: "Jump to Next Bookmark"
+            value: "다음 북마크로 이동"
           "Jump to Previous Bookmark":
-            value: "Jump to Previous Bookmark"
+            value: "이전 북마크로 이동"
       "Select Encoding":
-        value: "Select Encoding"
+        value: "인코딩 설정"
       "Go to Line":
-        value: "Go to Line"
+        value: "줄 번호로 이동"
       "Select Grammar":
-        value: "Select Grammar"
+        value: "문법 선택"
   View:
-    value: "View"
+    value: "보기"
     submenu:
       "Toggle Full Screen":
-        value: "Toggle Full Screen"
+        value: "전체화면 전환"
       Panes:
-        value: "Panes"
+        value: "패널"
         submenu:
           "Split Up":
-            value: "Split Up"
+            value: "위로 분할"
           "Split Down":
-            value: "Split Down"
+            value: "아래로 분할"
           "Split Left":
-            value: "Split Left"
+            value: "왼쪽으로 분할"
           "Split Right":
-            value: "Split Right"
+            value: "오른쪽으로 분할"
           "Focus Next Pane":
-            value: "Focus Next Pane"
+            value: "다음 패널로 포커스"
           "Focus Previous Pane":
-            value: "Focus Previous Pane"
+            value: "이전 패널로 포커스"
           "Focus Pane Above":
-            value: "Focus Pane Above"
+            value: "위 패널로 포커스"
           "Focus Pane Below":
-            value: "Focus Pane Below"
+            value: "아래 패널로 포커스"
           "Focus Pane On Left":
-            value: "Focus Pane On Left"
+            value: "왼쪽 패널로 포커스"
           "Focus Pane On Right":
-            value: "Focus Pane On Right"
+            value: "오른쪽 패널로 포커스"
           "Close Pane":
-            value: "Close Pane"
+            value: "패널 닫기"
       Developer:
-        value: "Developer"
+        value: "개발자"
         submenu:
           "Open In Dev Mode…":
-            value: "Open In Dev Mode..."
+            value: "개발 모드로 열기..."
           "Reload Window":
-            value: "Reload Window"
+            value: "창 다시 로드"
           "Run Package Specs":
-            value: "Run Package Specs"
+            value: "패키지 스팩 실행"
           "Toggle Developer Tools":
-            value: "Toggle Developer Tools"
+            value: "개발자 도구 토글"
       "Increase Font Size":
-        value: "Increase Font Size"
+        value: "폰트 크기 키우기"
       "Decrease Font Size":
-        value: "Decrease Font Size"
+        value: "폰트 크기 줄이기"
       "Reset Font Size":
-        value: "Reset Font Size"
+        value: "폰트 크기 원래대로"
       "Toggle Soft Wrap":
-        value: "Toggle Soft Wrap"
+        value: "소프트 랩핑 토글"
       "Toggle Command Palette":
-        value: "Toggle Command Palette"
+        value: "Command Palette 토글"
       "Toggle Tree View":
-        value: "Toggle Tree View"
+        value: "Tree View 토글"
   Selection:
-    value: "Selection"
+    value: "선택"
     submenu:
       "Add Selection Above":
-        value: "Add Selection Above"
+        value: "위에 선택 추가"
       "Add Selection Below":
-        value: "Add Selection Below"
+        value: "아래에 선택 추가"
       "Single Selection":
-        value: "Single Selection"
+        value: "단일 선택"
       "Split into Lines":
-        value: "Split into Lines"
+        value: "행으로 분할"
       "Select to Top":
-        value: "Select to Top"
+        value: "맨 위까지 선택"
       "Select to Bottom":
-        value: "Select to Bottom"
+        value: "맨 아래까지 선택"
       "Select Line":
-        value: "Select Line"
+        value: "행 선택"
       "Select Word":
-        value: "Select Word"
+        value: "단어 선택"
       "Select to Beginning of Word":
-        value: "Select to Beginning of Word"
+        value: "단어의 처음까지 선택"
       "Select to Beginning of Line":
-        value: "Select to Beginning of Line"
+        value: "행의 처음까지 선택"
       "Select to First Character of Line":
-        value: "Select to First Character of Line"
+        value: "행의 첫 문자까지 선택"
       "Select to End of Word":
-        value: "Select to End of Word"
+        value: "단어의 마지막까지 선택"
       "Select to End of Line":
-        value: "Select to End of Line"
+        value: "행의 마지막까지 선택"
       "Select Inside Brackets":
-        value: "Select Inside Brackets"
+        value: "괄호 안쪽 선택"
   Find:
-    value: "Find"
+    value: "찾기"
     submenu:
       "Find in Buffer":
-        value: "Find in Buffer"
+        value: "버퍼에서 찾기"
       "Replace in Buffer":
-        value: "Replace in Buffer"
+        value: "버퍼에서 바꾸기"
       "Select Next":
-        value: "Select Next"
+        value: "다음 선택"
       "Select All":
-        value: "Select All"
+        value: "전체 선택"
       "Toggle Find in Buffer":
-        value: "Toggle Find in Buffer"
+        value: "버퍼에서 찾기 토글"
       "Find in Project":
-        value: "Find in Project"
+        value: "프로젝트에서 찾기"
       "Toggle Find in Project":
-        value: "Toggle Find in Project"
+        value: "프로젝트에서 찾기 토글"
       "Find Next":
-        value: "Find Next"
+        value: "다음 찾기"
       "Find Previous":
-        value: "Find Previous"
+        value: "이전 찾기"
       "Replace Next":
-        value: "Replace Next"
+        value: "다음 바꾸기"
       "Replace All":
-        value: "Replace All"
+        value: "모두 바꾸기"
       "Clear History":
-        value: "Clear History"
+        value: "기록 지우기"
       "Find Buffer":
-        value: "Find Buffer"
+        value: "버퍼 찾기"
       "Find File":
-        value: "Find File"
+        value: "파일 찾기"
       "Find Modified File":
-        value: "Find Modified File"
+        value: "변경된 파일 찾기"
   Packages:
-    value: "Packages"
+    value: "패키지"
   Window:
-    value: "Window"
+    value: "창"
     submenu:
       Minimize:
-        value: "Minimize"
+        value: "최소화"
       Zoom:
-        value: "Zoom"
+        value: "줌"
       "Bring All to Front":
-        value: "Bring All to Front"
+        value: "모두 앞으로 가져오기"
   Help:
-    value: "Help"
+    value: "도움말"
     submenu:
       "Terms of Use":
-        value: "Terms of Use"
+        value: "이용 약관"
       Documentation:
-        value: "Documentation"
+        value: "문서"
       Roadmap:
-        value: "Roadmap"
+        value: "로드맵"
       "Frequently Asked Questions":
-        value: "Frequently Asked Questions"
+        value: "자주 묻는 질문"
       "Community Discussions":
-        value: "Community Discussions"
+        value: "커뮤니티 토론"
       "Report Issue":
-        value: "Report Issue"
+        value: "이슈 보고"
       "Search Issues":
-        value: "Search Issues"
+        value: "이슈 찾기"
       "Welcome Guide":
-        value: "Welcome Guide"
+        value: "환영합니다"


nothing

nothing

--- server/commons/logging.coffee
+++ server/commons/logging.coffee
@@ -5,4 +5,4 @@
   winston.add(winston.transports.Console,
     colorize: true,
     timestamp: true
-  )+  )


Dispatching the `on_activate` event just for the last active process in the array instead of every active process.

--- www/src/theoricus/core/processes.coffee
+++ www/src/theoricus/core/processes.coffee
@@ -190,4 +190,5 @@
         @the.config.disable_transitions = @disable_transitions
         @disable_transitions = null

-      _.each @active_processes, (process)-> process.on_activate?()+      # calls the activate for the last active process only
+      (_.last @active_processes).on_activate?()


Set defaults when creating a new registration

--- app/assets/javascripts/admin/routers/registrations.js.coffee
+++ app/assets/javascripts/admin/routers/registrations.js.coffee
@@ -27,6 +27,7 @@
     registration = new Augury.Models.Registration
     Augury.registrations.add registration
     registration.set filters: []
+    registration.set options: retries_allowed: false
     view = new Augury.Views.Registrations.Edit(model: registration, parameters: @parameters, keys: Augury.keys)
     $("#integration_main").html view.render().el


Nginx: use publicPort

Nginx: use publicPort

--- deployment/nginx.coffee
+++ deployment/nginx.coffee
@@ -258,7 +258,8 @@
     # i have added  to koding-sandbox, koding-load, koding-prod and koding-prod-deployment-sg
     server {
       # just a random port
-      listen #{if environment is "dev" then 8091 else 81};
+
+      listen #{parseInt(KONFIG.publicPort)+1+''};

       # why we have 2 different if checks? because www redirector block catches
       # all the requests, we should be more precise with the host
@@ -287,7 +288,7 @@
       "}

       # do not add hostname here!
-      listen #{if environment is "dev" then 8090 else 80};
+      listen #{KONFIG.publicPort};
       # root /usr/share/nginx/html;
       index index.html index.htm;
       location = /healthcheck {


fix bert's bug

fix bert's bug

--- app/assets/javascripts/views/staffplans/assignment.js.coffee
+++ app/assets/javascripts/views/staffplans/assignment.js.coffee
@@ -110,15 +110,15 @@

     unless client?
       StaffPlan.addClientByName clientNameValue, (client, reponse) =>
-        @model.set
-          client_id: client.get('id')
-        , silent: true
         @addProjectByNameAndClient client

     else
       @addProjectByNameAndClient client

   addProjectByNameAndClient: (client) ->
+    @model.set
+      client_id: client.get('id')
+    , silent: true
     projectNameValue = @$el.find('[data-model="Project"][data-attribute="name"]').val()
     project = StaffPlan.projects.detect (project) ->
       ( project.get("name") is projectNameValue ) and ( project.get("client_id") is client.get('id') )


fix loading bug in new files

fix loading bug in new files

fixes: CNVS-15208

test plan
* enable new files
* create one or two folders in the root folder
* from the root folder, click on another folder
* you should not get a react invariant error in
  the console

Change-Id: Id72543b0e0dd5598b3141fe620dcb56a32da93fc
Reviewed-on: https://gerrit.instructure.com/40788
Tested-by: Jenkins <d95b56ce41a2e1ac4cecdd398defd7414407cc08@instructure.com>
Reviewed-by: Jason Madsen <bcb5fff571a20f07c35d17ba9c364855c776dce7@instructure.com>
QA-Review: Clare Strong <40d6bb3ed7fef516c73274131d5a837c16de74fd@instructure.com>
Product-Review: Ryan Shaw <ea3cd978650417470535f3a4725b6b5042a6ab59@instructure.com>

--- app/coffeescripts/react_files/components/PublishCloud.coffee
+++ app/coffeescripts/react_files/components/PublishCloud.coffee
@@ -14,7 +14,11 @@
     getInitialState: -> @extractStateFromModel( @props.model )

     componentWillMount: ->
-      @props.model.on 'change', (model) => @setState(@extractStateFromModel( model ))
+      setState = (model) => @setState(@extractStateFromModel( model ))
+      @props.model.on('change', setState, this)
+
+    componentWillUnmount: ->
+      @props.model.off(null, null, this)

     # == Custom Functions == #


remove if

remove if

--- app/utils/connector-rfb.coffee
+++ app/utils/connector-rfb.coffee
@@ -27,10 +27,9 @@
     @rfb.connect ENV.deviceFarmHost, ENV.deviceFarmPort, '1234', "#{ENV.deviceFarmPath}?token=#{@deviceToken}"

   resize: ->
-    if @rfb.get_display
-      display = @rfb.get_display
-      scaleRatio = display.autoscale 100, 100, true
-      @rfb.get_mouse().set_scale scaleRatio
+    display = @rfb.get_display
+    scaleRatio = display.autoscale 100, 100, true
+    @rfb.get_mouse().set_scale scaleRatio

   disconnect: ->
     @rfb.disconnect()


handle absolute coordinate indices for multiple models

--- lib/assets/javascripts/jax/builtin/meshes/obj/parser.js.coffee
+++ lib/assets/javascripts/jax/builtin/meshes/obj/parser.js.coffee
@@ -1,6 +1,9 @@
 class Jax.Mesh.OBJ.Parser
   constructor: (content) ->
     @objects = {}
+    @vertices = []
+    @textureCoords = []
+    @normals = []
     curObj = null
     lines = []
     for line in content.split /\n/
@@ -9,9 +12,9 @@
         args = line.split /\s+/
         switch cmd = args.shift()
           when 'o'  then curObj = @objects[args.shift()] =
-            vertices: []
-            textureCoords: []
-            normals: []
+            vertices: @vertices
+            textureCoords: @textureCoords
+            normals: @normals
             faces: []
             aggregates: {}
             smooth: false


Added function to clear aria-describedby

--- app/assets/javascripts/frontend/form-validation.js.coffee
+++ app/assets/javascripts/frontend/form-validation.js.coffee
@@ -17,6 +17,9 @@
     else
       container.closest(".question-block").find(".govuk-error-message").empty()
     container.closest(".govuk-form-group--error").removeClass("govuk-form-group--error")
+
+  clearAriaDescribedby: (container) ->
+    container.closest('input,textarea,select').filter(':visible').removeAttr("aria-describedby")

   addErrorMessage: (question, message) ->
     @appendMessage(question, message)
@@ -524,6 +527,7 @@

     $(document).on "change", ".question-block input, .question-block select, .question-block textarea", ->
       self.clearErrors $(this)
+      self.clearAriaDescribedby $(this)
       self.validateIndividualQuestion($(@).closest(".question-block"), $(@))

   validateIndividualQuestion: (question, triggeringElement) ->


Removes debugger statement

Removes debugger statement

--- app/assets/javascripts/sprangular/services/account.coffee
+++ app/assets/javascripts/sprangular/services/account.coffee
@@ -50,7 +50,6 @@

     guestLogin: (data) ->
       email = if data is undefined then null else data.email
-      debugger
       params =
         'order[email]': email
       $http.post('/api/cart/guest_login.json', $.param(params))


Added optional units to chloropleths.

Added optional units to chloropleths.

--- app/assets/javascripts/visualization/choropleth.js.coffee
+++ app/assets/javascripts/visualization/choropleth.js.coffee
@@ -36,7 +36,7 @@
   # Build HTML legend for given choropleth computed layer
   buildLegend: () ->
     html  = "
"
-    html += "
#{@layer.label}
"
+    html += "
#{@layer.label}"+ if @layer.unit then " (#{@layer.unit})" else "" +"
"
     html += "
"
     html += "#{@grades[0].minLabel}"
     html += "#{@grades[@levelNumber - 1].maxLabel}"


update-to-error-reporting-system

update-to-error-reporting-system

--- lib/assets/javascripts/directives/ngdestroy.js.coffee
+++ lib/assets/javascripts/directives/ngdestroy.js.coffee
@@ -20,8 +20,10 @@
             list = list[childScope]
         else
           list = scope[factory]
-        list.drop(scope[modelName])
+        resource = list #Save resource for later if server returns success
         list = $injector.get(factory)
         object = {id: scope[modelName].id}
-        list.delete object, (returnData)->
+        list.delete(object).$promise #remove from server
+        .then (returnData)->
+          resource.drop(scope[modelName]) #remove from view
           ngCallbackCtrl.evaluate(returnData) if !!ngCallbackCtrl


Improve error handling

Improve error handling

--- server/routes/api/users.coffee
+++ server/routes/api/users.coffee
@@ -72,7 +72,8 @@
       mailer.sendMail mailOptions, (err) ->
         done(err, 'done');
   ], (err) ->
-    res.send 200, {}
+    return res.send err, 400 if err
+    res.send {}, 200

 app.get '/reset/:token', (req, res) ->
   User.findOne resetPasswordToken: req.params.token, resetPasswordExpires: $gt: Date.now(), (err, user) ->


Slight refactor ChangeView

Slight refactor ChangeView

Do not update location.hash by state any more.
Use location.hash -> state single way data flow.

--- app/assets/javascripts/1-components/change_view.js.coffee
+++ app/assets/javascripts/1-components/change_view.js.coffee
@@ -268,26 +268,21 @@
     window.removeEventListener 'hashchange', @handleLocationHashChange
     return

-  componentDidUpdate: (prevProps, prevState) ->
-    @setLocationHash()
-    return
-
   getInitialState: ->
     revisionId = _.max(@props.revisions.map((x) -> x.revisionId))
     revisionA: {id: revisionId, side: 'a'}
     revisionB: {id: revisionId, side: 'b'}

   handleRevisionTagClick: (side, revision, e) ->
-    state = {}
-    state["revision#{side}"] = revision
+    newHash = {}
+    revisionToString = (revision) -> "#{revision.id}#{revision.side.toLowerCase()}"
     if e.shiftKey
       # fill two sides
       ['a', 'b'].forEach (side) ->
-        state["revision#{side.toUpperCase()}"] = {
-          id: revision.id
-          side: side
-        }
-    @setState state
+        newHash[side.toUpperCase()] = revisionToString id: revision.id, side: side
+    else
+      newHash[side] = revisionToString(revision)
+    updateLocationHash newHash

   handleLocationHashChange: ->
     newState = {}
@@ -324,16 +319,6 @@
       # callback may be not ready, use setTimeout to defer the jump
       setTimeout((-> Callbacks.fire 'jumpToFileLine', {line, pathname}), 1)

-  setLocationHash: ->
-    state = @state
-    hashMap = {}
-    # append revision information
-    ['A', 'B'].forEach (side) ->
-      revision = state["revision#{side}"]
-      if revision.id >= 0
-        hashMap[side] = "#{revision.id}#{revision.side}"
-    @lastLocationHash = updateLocationHash hashMap
-
   render: ->
     props = @props
     state = @state


Small update in the tooltips to adjust the name of some methods to a global "mconf" object.

--- app/assets/javascripts/app/application/tooltips.js.coffee
+++ app/assets/javascripts/app/application/tooltips.js.coffee
@@ -1,4 +1,10 @@
-window.bindTooltips = ->
+mconf = window.mconf or= {}
+mconf.tooltips = {}
+
+mconf.tooltips.create = (obj, options={}) ->
+  obj.qtip options
+
+mconf.tooltips.bind = ->
   # Inserts a tooltip for every element with the class 'tooltipped'
   # Uses qTip
   # Examples:
@@ -24,8 +30,8 @@
     else
       at += " center"
       my += " center"
-    target = if obj.hasClass("from-mouse") then 'mouse' else obj
-    obj.qtip
+    target = if obj.hasClass("from-mouse") then "mouse" else obj
+    options =
       position:
         my: my
         at: at
@@ -34,6 +40,7 @@
           method: "shift"
       style:
         classes: "ui-tooltip-tipsy ui-tooltip-mconf"
+     mconf.tooltips.create obj, options

   # A tooltip in the format of a label, inside the component (used mainly
   # for images)
@@ -43,7 +50,7 @@
       at = "bottom center"
     else
       at = "top center"
-    obj.qtip
+    options =
       position:
         my: "center"
         at: at
@@ -52,6 +59,7 @@
           method: "shift"
       style:
         classes: "ui-tooltip-tipsy ui-tooltip-mconf-label"
+     mconf.tooltips.create obj, options

 $ ->
-  bindTooltips()
+  mconf.tooltips.bind()


Fixes #3445: Admin sidebar scrolls up on click on translations menu

--- app/assets/javascripts/app/controllers/translation.coffee
+++ app/assets/javascripts/app/controllers/translation.coffee
@@ -5,6 +5,7 @@
     'click .js-pushChanges': 'pushChanges'
     'click .js-resetChanges': 'resetChanges'
     'click .js-syncChanges': 'syncChanges'
+  initialRenderingDone: false

   constructor: ->
     super
@@ -38,6 +39,7 @@
       url:   "#{@apiPath}/translations/admin/lang/#{@locale}"
       processData: true
       success: (data, status, xhr) =>
+        @initialRenderingDone = true
         @times                = []
         @stringsNotTranslated = []
         @stringsTranslated    = []
@@ -49,6 +51,8 @@
               @stringsNotTranslated.push item
             else
               @stringsTranslated.push item
+
+        @untranslatedAtLastRender = $.extend({}, App.i18n.getNotTranslated(@locale))

         if !@translationToDo || event is 'render'
           @translationToDo = new TranslationToDo(
@@ -80,12 +84,13 @@
     )

   show: =>
+    return if @initialRenderingDone is false
+
     # see https://github.com/zammad/zammad/issues/2056
-    @untranslatedAtLastRender ||= $.extend({}, App.i18n.getNotTranslated(@locale))
-    return if _.isEqual(@untranslatedAtLastRender, App.i18n.getNotTranslated(@locale))
-
-    @untranslatedAtLastRender = $.extend({}, App.i18n.getNotTranslated(@locale))
-    App.Event.trigger('ui:rerender')
+    return if _.isEmpty(App.i18n.getNotTranslated(@locale))
+    return if @untranslatedAtLastRender && _.isEqual(@untranslatedAtLastRender, App.i18n.getNotTranslated(@locale))
+
+    @render()

   hide: =>
     @rerender()


fixed merge for subject-set-viewer.cjsx

fixed merge for subject-set-viewer.cjsx

--- app/assets/javascripts/components/subject-set-viewer.cjsx
+++ app/assets/javascripts/components/subject-set-viewer.cjsx
@@ -52,21 +52,22 @@
     # console.log 'SUBJECT-SET-VIEWER::render(), subject_index = ', @props.subject_index
     # NOTE: LightBox does not receive correct @props.subject_index. Why? --STI
     <div className={"subject-set-viewer" + if @props.subject_set.subjects.length <= 1 then ' single-page' else '' }>
-      {
-        if @props.subject_set.subjects.length > 1
-          <LightBox
-            subject_set={@props.subject_set}
-            subject_index={@props.subject_index}
-            key={@props.subject_set.subjects[0].id}
-            isDisabled={disableLightBox}
-            toggleLightboxHelp={@props.lightboxHelp}
-            onSubject={@specificSelection.bind this, @props.subject_index}
-            subjectCurrentPage={@props.subjectCurrentPage}
-            nextPage={@props.nextPage}
-            prevPage={@props.prevPage}
-            totalSubjectPages={@props.totalSubjectPages}
-            />
-        }
+

+        {
+          if @props.subject_set.subjects.length > 1
+            <LightBox
+              subject_set={@props.subject_set}
+              subject_index={@props.subject_index}
+              key={@props.subject_set.subjects[0].id}
+              isDisabled={disableLightBox}
+              toggleLightboxHelp={@props.lightboxHelp}
+              onSubject={@specificSelection.bind this, @props.subject_index}
+              subjectCurrentPage={@props.subjectCurrentPage}
+              nextPage={@props.nextPage}
+              prevPage={@props.prevPage}
+              totalSubjectPages={@props.totalSubjectPages}
+              />
+          }

       <SubjectZoomPan subject={@props.subject_set.subjects[@props.subject_index]} onChange={@handleZoomPanViewBoxChange} viewBox={@state.zoomPanViewBox}/>


Fixed so summernote editor saves correctly

--- app/assets/javascripts/godmin/summernote-editor.js.coffee
+++ app/assets/javascripts/godmin/summernote-editor.js.coffee
@@ -26,5 +26,5 @@

   # to get code for summernote
   summer_note.closest('form').submit ->
-    summer_note.val summer_note.code()[0]
+    summer_note.val summer_note.code()
     true


OX-322 Fix Show Cell edge

OX-322 Fix Show Cell edge

--- app/assets/javascripts/oxalis/geometries/celllayer.coffee
+++ app/assets/javascripts/oxalis/geometries/celllayer.coffee
@@ -23,8 +23,7 @@
     edgeGeometry.dynamic = true

     @edgeBuffer = new Float32Array(MAX_EDGE_POINTS * 3)
-    #{color: 0xff0000, linewidth: 2}, THREE.LineStrip
-    @edge = new THREE.Line(edgeGeometry, new THREE.LineBasicMaterial(), THREE.LinePieces)
+    @edge = new THREE.Line(edgeGeometry, new THREE.LineBasicMaterial({color: 0xff0000, linewidth: 4}), THREE.LineStrip)
     @curIndex = 0

   getMeshes : ->
@@ -38,9 +37,12 @@

       @edgeBuffer.set(pos, @curIndex * 3)
       @edge.geometry.__vertexArray = @edgeBuffer
+      @edge.geometry.__webglLineCount = @curIndex
       @edge.geometry.verticesNeedUpdate = true

       @curIndex++
+      if @curIndex % 100 == 0
+        console.log "Celllayer curIndex:", @curIndex, "MAX_EDGE_POINTS", MAX_EDGE_POINTS
       @flycam.hasChanged = true

   # Helper function


#1436 Bug fix

#1436 Bug fix

--- app/assets/javascripts/oxalis/model/binary/plane2d.coffee
+++ app/assets/javascripts/oxalis/model/binary/plane2d.coffee
@@ -26,14 +26,14 @@
   TEXTURE_SIZE_P : 0
   BUCKETS_PER_ROW : 0
   MAP_SIZE : 0
-  RECURSION_PLACEHOLDER : {}
+  RECURSION_PLACEHOLDER : {recursionPlaceholder: true}
   DELTA : [0, 5, 10]
   U : 0
   V : 0
   W : 0

   NOT_LOADED_BUCKET_INTENSITY : 100
-  NOT_LOADED_BUCKET_PLACEHOLDER : {}
+  NOT_LOADED_BUCKET_PLACEHOLDER : {notLoadedBucketPlaceholder: true}

   cube : null
   queue : null
@@ -41,7 +41,7 @@
   dataTexture : null

-  constructor : (index, @cube, @queue, @TEXTURE_SIZE_P, @DATA_BIT_DEPTH,
+  constructor : (@index, @cube, @queue, @TEXTURE_SIZE_P, @DATA_BIT_DEPTH,
                  @TEXTURE_BIT_DEPTH, @MAPPED_DATA_BIT_DEPTH, isSegmentation) ->

     _.extend(this, Backbone.Events)
@@ -60,7 +60,7 @@
     for i in [0..@cube.LOOKUP_DEPTH_DOWN]
       @MAP_SIZE += 1 << (i << 1)

-    [@U, @V, @W] = Dimensions.getIndices(index)
+    [@U, @V, @W] = Dimensions.getIndices(@index)

     @dataTexture = { renderTile: @renderDataTile }

@@ -252,6 +252,7 @@
     bucket[@V] += tile[1]

     map = @generateRenderMap(bucket)
+
     @renderSubTile(map, 0, tile, @dataTexture.zoomStep)

@@ -267,10 +268,11 @@

     else if map[mapIndex] == @NOT_LOADED_BUCKET_PLACEHOLDER

+      tileSizeP = @cube.BUCKET_SIZE_P - (@dataTexture.zoomStep - tileZoomStep)
       @renderToBuffer(
         {
           buffer: @dataTexture.buffer
-          offset: bufferOffsetByTileMacro(@, tile, @cube.BUCKET_SIZE_P)
+          offset: bufferOffsetByTileMacro(@, tile, tileSizeP)
           widthP: @cube.BUCKET_SIZE_P
           rowDelta: 1 << @TEXTURE_SIZE_P
         }


Add an extra perf measurement

Add an extra perf measurement

--- app/js/jail_iframe/classes/performance_measurement.coffee
+++ app/js/jail_iframe/classes/performance_measurement.coffee
@@ -32,7 +32,7 @@
 .then( ->
   console.log document.readyState
   if window.performance && window.performance.timing
-    'fetchStart responseEnd domLoading domInteractive domContentLoadedEventEnd domComplete loadEventEnd'
+    'fetchStart responseEnd domLoading domInteractive domContentLoadedEventStart domContentLoadedEventEnd domComplete loadEventEnd'
     .split(' ').forEach (timing_event) ->
       add_existing_timing_event timing_event, window.performance.timing[timing_event]
   if FactlinkJailRoot.can_haz.log_jslib_loading_performance


New endpoint for getting info on current connected user

--- api/users.coffee
+++ api/users.coffee
@@ -4,6 +4,8 @@
 bcrypt = require 'bcrypt'
 User = require '../models/user'
 Team = require '../models/team'
+
+gameController = require '../controllers/game_controller'

 # CONTROLLER
@@ -16,6 +18,23 @@
         User.findAll().then (users) ->
             list.push formatUser(user) for user in users
             res.json list
+
+    app.get '/api/users/me', 'users.me', (req, res) ->
+        return unless req.checkAuthentication()
+        User.findOne
+            where: id: req.session.user.id
+        .done (user) ->
+            gameController.currentGame (game) ->
+                gameController.getGameUser game, user, (gameUser) ->
+                    gameController.getGameUser game, user, (gameUser) ->
+                        gameController.getGameTeamForUser game, user, (gameTeam) ->
+                            res.json
+                                gameTeam: gameTeam
+                                gameUser: gameUser
+                                user: formatUser(user)
+
+
+

     # GET /api/users/:id


Remove "focused: true" from winConfig.

Remove "focused: true" from winConfig.

According to:

  - https://bugzilla.mozilla.org/show_bug.cgi?id=1253129

and #2896, this:

1. causes Firefox to crash, and
2. isn't actually necessary.

So just remove it.

H/t @ris58h in #2896.

--- background_scripts/main.coffee
+++ background_scripts/main.coffee
@@ -192,7 +192,6 @@
     if request.registryEntry.options.incognito or request.registryEntry.options.window
       windowConfig =
         url: request.urls
-        focused: true
         incognito: request.registryEntry.options.incognito ? false
       chrome.windows.create windowConfig, -> callback request
     else


nginx: do not allow access to hubspot pages from team domains

--- deployment/nginx.coffee
+++ deployment/nginx.coffee
@@ -151,6 +151,9 @@
           proxy_next_upstream   error timeout   invalid_header http_500;
           proxy_connect_timeout 30;

+          if ($host !~* ^(dev|sandbox|latest|www)) {
+             return 301 /;
+          }

           proxy_pass #{proxy};
       }


removing id strategy for now. Will add back in

--- app/assets/javascripts/autocompleter.js.coffee
+++ app/assets/javascripts/autocompleter.js.coffee
@@ -10,17 +10,6 @@
   template: (entry)->
     "@#{entry}"

-doi_strategy =
-  match: /(10.(\d)+/([^(\s\>\"\<)])+)/;
-  search: (name, callback)->
-    search_call = $.getJSON("/user_lookup",{name: name})
-    search_call.done (result)->
-      callback( result.map (r)-> r.name)
-    search_call.fail -> callback([],true)
-  replace: (entry)->
-    " @#{entry} "
-  template: (entry)->
-    "@#{entry}"

 stratagies = [username_strategy]


Add additional fixes for new text-buffer events API

--- spec/results-model-spec.coffee
+++ spec/results-model-spec.coffee
@@ -66,7 +66,7 @@

         # updates when there are no matches
         editor.setText('no matches in here')
-        editor.buffer.emit('contents-modified')
+        advanceClock(editor.buffer.stoppedChangingDelay)

         expect(resultAddedSpy.callCount).toBe 2
         expect(resultRemovedSpy.callCount).toBe 1
@@ -82,7 +82,7 @@
         spyOn(editor, 'scan').andCallThrough()

         editor.setText('no matches in here')
-        editor.buffer.emit('contents-modified')
+        advanceClock(editor.buffer.stoppedChangingDelay)

         expect(editor.scan).not.toHaveBeenCalled()

@@ -108,7 +108,7 @@
         editor = atom.workspaceView.getActiveView().editor
         editor.setText('items\nitems')
         spyOn(editor, 'scan').andCallThrough()
-        editor.buffer.emit('contents-modified')
+        advanceClock(editor.buffer.stoppedChangingDelay)
         expect(editor.scan).not.toHaveBeenCalled()

   describe "cancelling a search", ->


Update specs for new SettingsView API

Update specs for new SettingsView API

--- spec/settings-view-spec.coffee
+++ spec/settings-view-spec.coffee
@@ -20,19 +20,19 @@
       expect(newSettingsView.activePanelName).toBe 'Themes'

     it "shows the previously active panel if it is added after deserialization", ->
-      settingsView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
+      settingsView.addCorePanel('Panel 1', 'panel1', $$ -> @div id: 'panel-1')
       settingsView.showPanel('Panel 1')
       newSettingsView = new SettingsView(settingsView.serialize())
       newSettingsView.initializePanels()
       settingsView.remove()
       newSettingsView.attachToDom()
-      newSettingsView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
+      newSettingsView.addPanel('Panel 1', 'panel1', $$ -> @div id: 'panel-1')
       expect(newSettingsView.activePanelName).toBe 'Panel 1'

-  describe ".addPanel(name, view)", ->
+  describe ".addCorePanel(name, iconName, view)", ->
     it "adds a menu entry to the left and a panel that can be activated by clicking it", ->
-      settingsView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
-      settingsView.addPanel('Panel 2', $$ -> @div id: 'panel-2')
+      settingsView.addCorePanel('Panel 1', 'panel1', $$ -> @div id: 'panel-1')
+      settingsView.addCorePanel('Panel 2', 'panel2', $$ -> @div id: 'panel-2')

       expect(settingsView.panelMenu.find('li a:contains(Panel 1)')).toExist()
       expect(settingsView.panelMenu.find('li a:contains(Panel 2)')).toExist()


update atom configuration

update atom configuration

--- atom/config.cson
+++ atom/config.cson
@@ -35,9 +35,10 @@
     searchAllPanes: true
   "git-diff":
     showIconsInEditorGutter: true
-  linter:
-    showErrorTabLine: true
+  linter: {}
   "linter-eslint": {}
+  "linter-ui-default":
+    showPanel: true
   "markdown-preview":
     useGitHubStyle: true
   minimap:
@@ -49,6 +50,9 @@
     enableVcsColoring: true
   "tree-view":
     hideIgnoredNames: true
+  welcome:
+    showOnStartup: false
 ".html.php.text":
   editor:
     preferredLineLength: 120
+    tabLength: 4


Beautify Elm files on save

Beautify Elm files on save

--- atom/config.cson
+++ atom/config.cson
@@ -1,4 +1,7 @@
 "*":
+  "atom-beautify":
+    elm:
+      beautify_on_save: true
   "atom-ctags": {}
   "autocomplete-plus":
     enableAutoActivation: false


remove pigments from atom configuration

remove pigments from atom configuration

--- atom/config.cson
+++ atom/config.cson
@@ -43,9 +43,6 @@
     plugins:
       linter: true
       linterDecorationsZIndex: 0
-  pigments:
-    extendAutocompleteToColorValue: true
-    groupPaletteColors: "by file"
   tabs:
     enableVcsColoring: true
   "tree-view":


Switch atom to dark mode

Switch atom to dark mode

--- atom/config.cson
+++ atom/config.cson
@@ -13,8 +13,8 @@
     projectHome: "/Users/thomasmattachione/source"
     telemetryConsent: "no"
     themes: [
-      "one-light-ui"
-      "one-light-syntax"
+      "atom-dark-ui"
+      "atom-dark-syntax"
     ]
   editor:
     fontFamily: "Menlo, Monaco, 'Courier New', monospace"