Agent pie: start/end angle pie transition work

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -237,7 +237,10 @@
             if myInstanceDataId = 'resolved' and i = 0
                 console.log('in tween - OLD DATA - ' + myInstanceDataId + '[' + i + ']: ',window.oldPieData[myInstanceDataId][i])
             #console.log('1. in tween - d: ',d)
-            myInterpolater = d3.interpolate(window.oldPieData[myInstanceDataId][i] ? d, d)
+
+            #myInterpolater = d3.interpolate(window.oldPieData[myInstanceDataId][i] ? d, d)
+            myInterpolater = d3.interpolate(opd[i])
+
             #console.log('myInterpolater(0): ',myInterpolater(0))
             window.oldPieData[myInstanceDataId][i] = myInterpolater(0) ? d
             if myInstanceDataId = 'resolved' and i = 0


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -52,7 +52,7 @@
       endAngle: d.endAngle)
     (t) ->
       b = i(t)
-      @arc b
+      return @arc b

   removePieTween: (d, i) ->
     `var i`


Agent pie: code cleanup

Agent pie: code cleanup

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -149,9 +149,10 @@
             myInterpolater = d3.interpolate({
                 startAngle: s0
                 endAngle: e0
-            },
+            },{
                 startAngle: d.startAngle
-                endAngle: d.endAngle)
+                endAngle: d.endAngle
+            })
             return (t) ->
                 return arc(myInterpolater(t))
         )


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -99,8 +99,8 @@
         c = arc.centroid(d)
         x = c[0]
         y = c[1]
-        mx = 1.9
-        my = 1.1
+        mx = 1.5
+        my = .8
         h = Math.sqrt(x*x + y*y)
         r = labelRadius
         if x <= 0


Added simple variable assignment.

Added simple variable assignment.

--- src/pal/js-code-generator.coffee
+++ src/pal/js-code-generator.coffee
@@ -40,7 +40,6 @@
         func.call(@, @visit(node.declarations, '$body'), node)

     [@indent, header, body, @indent, '}\n']
-

@@ -138,6 +137,12 @@

       condition.concat [body, @indent, '}']

+    # Assignment may be a statement in Pal, but it's just an operator in
+    # JavaScript. I could have used @makeBinOp, but I wanted a more customized
+    # appearance. Not that it'll matter to eval().
+    assign: (node) ->
+      [@visit(node.left), ' = ', @visit(node.right)]
+
     sub_invocation: (node) ->
       params =
         @visit param for param in node.params
@@ -150,6 +155,12 @@
         if node.name is 'writeln' then '_output' else '_' + node.name

       "#{subroutineName}(#{paramList})"
+
+    # Variables are complicated, but I'm just going to do the following naïve
+    # thing: Just spit out a dollar and the name. The dollar is so that people
+    # don't name a Pal variable 'return' and make unparsable JavaScript.
+    variable: (node) ->
+      '$' + node.name

     # Got to place strings in quotes and escape characters.
     string: (node) ->


Fix exception if there is no content layer set

--- framer/Components/ScrollComponent.coffee
+++ framer/Components/ScrollComponent.coffee
@@ -93,6 +93,8 @@

 	calculateContentFrame: ->

+		return Utils.rectZero() unless @content
+
 		# Calculates the size of the content. By default this returns the total
 		# size of all the content layers based on width and height. You can override
 		# this for example to take scaling into account.
@@ -226,6 +228,8 @@
 			_.clone(@_contentInset)
 		set: (contentInset) ->
 			@_contentInset = Utils.rectZero(Utils.parseRect(contentInset))
+
+			return unless @content

 			# If we reset the content inset, we need to reset the content position
 			contentFrame = @calculateContentFrame()


Fix scroll position on resizing of a ScrollComponent

--- framer/Components/ScrollComponent.coffee
+++ framer/Components/ScrollComponent.coffee
@@ -160,6 +160,10 @@

 		@content.draggable.constraints = constraintsFrame

+		# Reset the scroll points to the right postions, this is needed so it can calculate
+		# the new scroll points within the updated constraints for this new size.
+		@scrollPoint = @scrollPoint
+
 		# Change the default background color if we added children. We keep the default
 		# color around until you set a content layer so you can see the ScrollComponent
 		# on your screen after creation.
@@ -438,6 +442,8 @@

 	# If we have an image set, it makes way more sense to add it to the
 	# background of the wrapper then the content.
+	# Note: I ran into a situation where this had a weird result, maybe
+	# we should revise this in the future.
 	if layer.image
 		scroll.image = layer.image
 		layer.image = null


svg fix para pug

svg fix para pug

--- gulp/tasks/svg.coffee
+++ gulp/tasks/svg.coffee
@@ -8,7 +8,7 @@
 config        = require './config'

-#This task outputs to the Jade Includes to place inline
+#This task outputs to the pug Includes to place inline
 gulp.task 'svg:inline', ->
   gulp.src './src/svg/inline/*.svg'
   .pipe $.plumber(errorHandler: onError)
@@ -24,7 +24,7 @@
     parserOptions :
       xmlMode : true
   )
-  .pipe gulp.dest './src/jade/layouts/includes'
+  .pipe gulp.dest './src/pug/layouts/includes'

 #This task outputs to the dist svg folder to use with cache etc.
 gulp.task 'svg:external', ->


Coffeescript migrations

Coffeescript migrations

--- src/server/utils/cakefile.coffee
+++ src/server/utils/cakefile.coffee
@@ -40,7 +40,7 @@
   @migrationCreate: (options) =>
       name = options.title or "unnamed"
       command = [".", "node_modules", "salad", "node_modules", ".bin", "sequelize"].join(path.sep)
-      migrate = spawn command, ["-c", name]
+      migrate = spawn command, ["--coffee", "-c", name]

       migrate.stdout.on "data", (data) =>
         console.log data.toString().replace(/\n$/m, '')
@@ -55,7 +55,7 @@
   @migrate: =>
     command = [".", "node_modules", "salad", "node_modules", ".bin", "sequelize"].join(path.sep)

-    migrate = spawn command, ["-e", Salad.env, "-m"]
+    migrate = spawn command, ["-e", Salad.env, "--coffee", "-m"]

     migrate.stdout.on "data", (data) =>
       console.log data.toString().replace(/\n$/m, '')


update pay banner

update pay banner

--- src/smc-webapp/project_page.cjsx
+++ src/smc-webapp/project_page.cjsx
@@ -229,10 +229,10 @@

     render_learn_more: (color) ->

-            <Space/> — learn more... <Space/>
+            <Space/> — Tell me more. <Space/>

         #@actions(project_id: @props.project_id).show_extra_free_warning()} style={color:'white', cursor:'pointer'}> learn more...

@@ -276,7 +276,7 @@

         <Alert bsStyle='warning' style={styles}>
             <Icon name='exclamation-triangle' style={float:'right', marginTop: '3px'}/>
-            <Icon name='exclamation-triangle' /> Upgrade this project, since it is {on a free server if host} {without network access if internet}.
+            <Icon name='exclamation-triangle' /> Support CoCalc by upgrading this project.  It is {on a trial server if host} {without network access if internet}.
             {@render_learn_more(styles.color)}
             {@render_dismiss()}
             {@extra(host, internet)}


Correct assertion.

Correct assertion.

--- src/spec/stockimport.spec.coffee
+++ src/spec/stockimport.spec.coffee
@@ -144,7 +144,7 @@
         s = stocks[1]
         expect(s.sku).toBe 'foo-bar-123'
         expect(s.quantityOnStock).toBe 0
-        expect(s.expectedDelivery).toBeUndefined()
+        expect(s.expectedDelivery).toBe ''
         expect(s.supplyChannel.typeId).toBe 'channel'
         expect(s.supplyChannel.id).toBe 'myChannelId'
         done()


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -59,7 +59,7 @@
         .attr("id","dropshadow")
     filter.append("feGaussianBlur")
         .attr("in","SourceAlpha")
-        .attr("stdDeviation","1.5")
+        .attr("stdDeviation","1.3")
         .attr("result","blur")
     filter.append("feOffset")
         .attr("in","blur")


Agent pie: test globalizing variables

Agent pie: test globalizing variables

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -3,51 +3,51 @@
     @accessor 'data'

     #@oldPieData: ''
-    @container: ''
+    #@container: ''

     ready: ->
         # Remove any previous svg
         $(@node).children('svg').remove()
         # Define the container
         @container = $(@node).parent()
-    #
-    # CONFIG ZONE
-    #
-
-    # Width of the SVG area
-    @width = (Dashing.widget_base_dimensions[0] * container.data('sizex')) - Dashing.widget_margins[0] * 4 * (container.data('sizex') - 1)
-
-    # Height of the SVG area allowing for header and footer text
-    @height = (Dashing.widget_base_dimensions[1] * container.data('sizey')) - 120
-
-    # Calculated min dimension of the SVG area
-    @radius = Math.min(width, height) / 2
-
-    # Outer radius of the pie
-    @radiuso = Math.min(width, height) / 3
-
-    # Inner radius of the pie (zero = pie, non-zero = donut)
-    @radiusi = radiuso * 2 / 3
-
-    # Color scale for pie slices
-    @color = d3.scale.category20()
-
-    # X-offset for drop shadow filter
-    @dropshadowx = 2
-
-    # Y-offset for drop shadow filter
-    @dropshadowy = 2
-
-    # [STRING] Blur value for drop shadow filter
-    @dropshadowblur = '1.2'
-
-    #
-    # END CONFIG ZONE
-    #
-
-    @pie = d3.layout.pie().value((d) -> d.value).sort(null)
-    @arc = d3.svg.arc().innerRadius(radiusi).outerRadius(radiuso)
-    @svg = d3.select(@node).append('svg').attr('width', width).attr('height', height).append('g').attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
+        #
+        # CONFIG ZONE
+        #
+
+        # Width of the SVG area
+        @width = (Dashing.widget_base_dimensions[0] * container.data('sizex')) - Dashing.widget_margins[0] * 4 * (container.data('sizex') - 1)
+
+        # Height of the SVG area allowing for header and footer text
+        @height = (Dashing.widget_base_dimensions[1] * container.data('sizey')) - 120
+
+        # Calculated min dimension of the SVG area
+        @radius = Math.min(width, height) / 2
+
+        # Outer radius of the pie
+        @radiuso = Math.min(width, height) / 3
+
+        # Inner radius of the pie (zero = pie, non-zero = donut)
+        @radiusi = radiuso * 2 / 3
+
+        # Color scale for pie slices
+        @color = d3.scale.category20()
+
+        # X-offset for drop shadow filter
+        @dropshadowx = 2
+
+        # Y-offset for drop shadow filter
+        @dropshadowy = 2
+
+        # [STRING] Blur value for drop shadow filter
+        @dropshadowblur = '1.2'
+
+        #
+        # END CONFIG ZONE
+        #
+
+        @pie = d3.layout.pie().value((d) -> d.value).sort(null)
+        @arc = d3.svg.arc().innerRadius(radiusi).outerRadius(radiuso)
+        @svg = d3.select(@node).append('svg').attr('width', width).attr('height', height).append('g').attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')

     onData: (data) ->
         #$(@node).fadeOut().fadeIn()


--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -184,8 +184,8 @@
             #console.log('TS D:', d)
             `var i`
             i = d3.interpolate({
-                startAngle: 0 #s0
-                endAngle: 0 #e0
+                startAngle: s0
+                endAngle: e0
             },
                 startAngle: d.startAngle
                 endAngle: d.endAngle)


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -252,9 +252,9 @@
             else
                 'M' + (d.r - 2) + ',' + d.b + 'L' + (d.l + 2) + ',' + d.b + ' ' + d.cx + ',' + d.cy

-        totaltickets = 0
+        totalTickets = 0
         for pd in dataSet
-            totaltickets += pd.value
+            totalTickets += pd.value
         #console.log totaltickets
         totalLabel.append('text')
             .text(totalTickets)


Agent pie code cleanup

Agent pie code cleanup

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -7,6 +7,11 @@
         @update(data.data)

     update: (dataSet) ->
+
+        # Remove any previous svg
+        $(@node).children('svg').remove()
+        # Define the container
+        container = $(@node).parent()

         # CONFIG ZONE :

@@ -43,11 +48,6 @@
             dataSet = @get('data')
         if !dataSet
             return
-
-        # Remove any previous svg
-        $(@node).children('svg').remove()
-
-        container = $(@node).parent()

         pie = d3.layout.pie().value((d) -> d.value).sort(null)
         arc = d3.svg.arc().innerRadius(radiusi).outerRadius(radiuso)


Agent pie: edit pointer transition

Agent pie: edit pointer transition

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -319,7 +319,7 @@
                 else
                     'M' + (d.r - 2) + ',' + d.b + 'L' + (d.l + 2) + ',' + d.b + ' ' + d.cx + ',' + d.cy
             )
-            .style('opacity',1)
+        pointers.transition().duration(500).style('opacity',0)

         # Display total count
         totalTickets = 0


Remove the horribleUpdateMethod

Remove the horribleUpdateMethod

--- src/text-editor-component.coffee
+++ src/text-editor-component.coffee
@@ -190,8 +190,6 @@
     else unless @updateRequested
       @updateRequested = true
       atom.views.updateDocument =>
-        @editor.horribleUpdateMethod?()
-        @editor.horribleUpdateMethod = null
         @updateRequested = false
         @updateSync() if @editor.isAlive()
       atom.views.readDocument(@readAfterUpdateSync)


Destroy TextEditorPresenter when unmounting TextEditorComponent

Fixes atom/find-and-replace#348

--- src/text-editor-component.coffee
+++ src/text-editor-component.coffee
@@ -149,6 +149,7 @@
     {editor, hostElement} = @props

     @unsubscribe()
+    @presenter.destroy()
     @scopedConfigSubscriptions.dispose()
     window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
     clearInterval(@domPollingIntervalId)


JVM: add reset default VM function

JVM: add reset default VM function

--- workers/social/lib/social/models/vm.coffee
+++ workers/social/lib/social/models/vm.coffee
@@ -22,6 +22,7 @@

   handleError = (err)-> console.error err  if err

+  VMDefaultDiskSize = 4096
   @set
     softDelete          : yes
     indexes             :
@@ -60,6 +61,8 @@
         count:
           (signature Object, Function)
         fetchDefaultVm:
+          (signature Function)
+        resetDefaultVMLimits:
           (signature Function)
         fetchVmRegion:
           (signature String, Function)
@@ -112,7 +115,7 @@
         default         : 1024
       diskSizeInMB      :
         type            : Number
-        default         : 3600
+        default         : VMDefaultDiskSize
       numCPUs           :
         type            : Number
         default         : 1
@@ -140,6 +143,16 @@
           groups   : { $elemMatch: id: fetchedGroup.getId() }
           planCode : 'free'
         , callback
+
+
+  @resetDefaultVMLimits = secure (client, callback)->
+    fetchDefaultVmHelper client, (err, vm)->
+      return callback err  if err
+      return callback new Error "VM not found" unless vm
+      vm.update {$set: diskSizeInMB: VMDefaultDiskSize}, (err) ->
+        return callback err if err
+        callback null, vm.hostnameAlias
+
   @createDomains = (account, domains, hostnameAlias)->

     updateRelationship = (domainObj)->


Only apply doc changes, not fold changes in undo manager

--- services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor/undo/UndoManager.coffee
@@ -207,16 +207,19 @@
 			return doc.split("\n")

 		_aceDeltaSetsToSimpleDeltaSets: (aceDeltaSets, docLines) ->
+			simpleDeltaSets = []
 			for deltaSet in aceDeltaSets
-				simpleDeltas = []
-				for delta in deltaSet.deltas
-					simpleDeltas.push @_aceDeltaToSimpleDelta(delta, docLines)
-					docLines = @_applyAceDeltasToDocLines([delta], docLines)
-				{
-					deltas: simpleDeltas
-					group: deltaSet.group
-				}
-
+				if deltaSet.group == "doc" # ignore fold changes
+					simpleDeltas = []
+					for delta in deltaSet.deltas
+						simpleDeltas.push @_aceDeltaToSimpleDelta(delta, docLines)
+						docLines = @_applyAceDeltasToDocLines([delta], docLines)
+					simpleDeltaSets.push {
+						deltas: simpleDeltas
+						group: deltaSet.group
+					}
+			return simpleDeltaSets
+
 		_simpleDeltaSetsToAceDeltaSets: (simpleDeltaSets, docLines) ->
 			for deltaSet in simpleDeltaSets
 				aceDeltas = []


Implement page:before-change

Implement page:before-change

--- src/turbolinks/controller.coffee
+++ src/turbolinks/controller.coffee
@@ -63,8 +63,18 @@

   clickBubbled: (event) =>
     if not event.defaultPrevented and location = @getVisitableLocationForEvent(event)
-      event.preventDefault()
-      @visit(location)
+      if @triggerEvent("page:before-change", data: { url: location }, cancelable: true)
+        event.preventDefault()
+        @visit(location)
+
+  # Events
+
+  triggerEvent: (eventName, {cancelable, data} = {}) ->
+    event = document.createEvent("events")
+    event.initEvent(eventName, true, cancelable is true)
+    event.data = data
+    document.dispatchEvent(event)
+    not event.defaultPrevented

   # Private


errors -- change something from visible alert to console log

--- salvus/client.coffee
+++ salvus/client.coffee
@@ -368,7 +368,7 @@
             when "error"
                 # An error that isn't tagged with an id -- some sort of general problem.
                 if not mesg.id?
-                    alert_message(type:"error", message:mesg.error)
+                    console.log("WARNING: #{mesg.error}")
                     return

         id = mesg.id  # the call f(null,mesg) can mutate mesg (!), so we better save the id here.


Board js reload 的問題

Board js reload 的問題

--- app/assets/javascripts/boards.coffee
+++ app/assets/javascripts/boards.coffee
@@ -3,35 +3,45 @@
 # You can use CoffeeScript in this file: http://coffeescript.org/

 $ ->
-  $('input#board_player_anonymous').keyup ->
-    anonymous = $(this).val().trim()
-    unless anonymous
+  initialize = ->
+    $('input#board_player_anonymous').keyup ->
+      anonymous = $(this).val().trim()
+      unless anonymous
+        $('.players').addClass('hide')
+        $('input#board_player_player_id').val('')
+      else
+        $.ajax
+          dataType: "json"
+          url: '/boards/search'
+          data: {name: anonymous}
+          success: (data) ->
+            $('.messages-list').html('')
+            $('.players').removeClass('hide') if data.result.length > 0
+
+            $.each data.result, (key, val) ->
+              message = $('#new_player .message.sample').clone().removeClass('sample').removeClass('hide')
+              message.find('.message-avatar').attr('src', "http://graph.facebook.com/v2.2/#{val.fid}/picture?type=normal")
+              message.find('.message-subject').html(val.name)
+              message.attr('data-uid', val.id)
+
+              message.appendTo('.messages-list')
+
+    $(document).on "click", ".messages-list > .message", (event) ->
+      message = $(this)
+      $('#board_player_player_id').val(message.data('uid'))
+      $('input#board_player_anonymous').val(message.find('a').html())
       $('.players').addClass('hide')
+
+    $('#new_player').on 'hidden.bs.modal', ->
+      $('.players').addClass('hide')
+      $('input#board_player_anonymous').val('')
       $('input#board_player_player_id').val('')
-    else
-      $.ajax
-        dataType: "json"
-        url: '/boards/search'
-        data: {name: anonymous}
-        success: (data) ->
-          $('.messages-list').html('')
-          $('.players').removeClass('hide') if data.result.length > 0

-          $.each data.result, (key, val) ->
-            message = $('#new_player .message.sample').clone().removeClass('sample').removeClass('hide')
-            message.find('.message-avatar').attr('src', "http://graph.facebook.com/v2.2/#{val.fid}/picture?type=normal")
-            message.find('.message-subject').html(val.name)
-            message.attr('data-uid', val.id)
+    # --

-            message.appendTo('.messages-list')

-  $(document).on "click", ".messages-list > .message", (event) ->
-    message = $(this)
-    $('#board_player_player_id').val(message.data('uid'))
-    $('input#board_player_anonymous').val(message.find('a').html())
-    $('.players').addClass('hide')

-  $('#new_player').on 'hidden.bs.modal', ->
-    $('.players').addClass('hide')
-    $('input#board_player_anonymous').val('')
-    $('input#board_player_player_id').val('')
+
+
+  $(document).ready(initialize)
+  $(document).on('page:load', initialize)


[Fix] Remove ',' in deploy

[Fix] Remove ',' in deploy

--- app/assets/javascripts/deploy.coffee
+++ app/assets/javascripts/deploy.coffee
@@ -9,7 +9,7 @@
         chunkUrl = data.url
         if data.chunks.length > 0
           chunk_text = data.chunks.map (chunk) -> chunk.text
-          $("code").append(colorize(chunk_text.join()))
+          $("code").append(colorize(chunk_text.join('')))
         if data.deploy.status != 'pending' && data.deploy.status != 'running'
           clearTimeout(tid)
     tid = setInterval func, 500


turbolinks fix report

turbolinks fix report

--- app/assets/javascripts/report.coffee
+++ app/assets/javascripts/report.coffee
@@ -3,7 +3,7 @@
   $('#locaties tr.location_raw, #locaties tr.span-6').show()

 $(document).on 'ready', reportInit
-$(document).on 'turbolinks:request-start', reportInit
+$(document).on 'turbolinks:load', reportInit

 $(document).on 'click', '#locaties tr.span-6 td[colspan], #locaties tr.span-4 td[colspan]', (event_super_row_click)->


Change all non-singleton categories to record completer

--- app/assets/volume/spreadsheet.coffee
+++ app/assets/volume/spreadsheet.coffee
@@ -283,13 +283,14 @@
             td.id = i
           td

-        generateMultiple = (cat, cols, row, i, n, t, m) ->
+        generateMultiple = (col, cols, row, i, n, t) ->
           if n == undefined
             return if t == 1
           else
             return if n < t
           td = row.appendChild(document.createElement('td'))
           td.setAttribute("colspan", cols)
+          cat = col.category
           if n == undefined && t > 1
             td.appendChild(document.createTextNode(t + " " + cat.name + "s"))
             td.className = 'more'
@@ -302,10 +303,13 @@
               else if editing
                 td.appendChild(document.createTextNode("add " + cat.name))
               if editing
-                if cols > 1 && m != undefined
-                  generateCell(row, undefined, undefined, id+'-rec_'+i+'_'+(n||0)+'_'+m)
-                  row.appendChild(td)
-                  td.setAttribute("colspan", cols-1)
+                if 'metrics' of col && col.metrics[0].id != 'id'
+                  generateCell(row, undefined, undefined, id+'-rec_'+i+'_'+(n||0)+'_'+col.start)
+                  if cols > 1
+                    row.appendChild(td)
+                    td.setAttribute("colspan", cols-1)
+                  else
+                    row.removeChild(td)
                 td.className = 'null add'
                 td.id = id + '-add_' + i + '_' + cat.id
           td
@@ -316,7 +320,7 @@
           c = col.category.id
           t = counts[i][c] || 0
           r = records[c]
-          if td = generateMultiple(col.category, l, row, i, n, t, col.start)
+          if td = generateMultiple(col, l, row, i, n, t)
             if n == undefined
               for n in [0..t-1] by 1
                 td.classList.add('ss-rec_' + r.id[n][i])
@@ -339,7 +343,7 @@

         generateAsset = (row, i, n) ->
           a = assets[i]
-          return if generateMultiple(pseudoCategory.asset, 3, row, i, n, a.length)
+          return if generateMultiple({category:pseudoCategory.asset}, 3, row, i, n, a.length)
           b = i
           if n == undefined
             a = a[0]


transcription tags as inputs, not buttons

--- app/classifier/tasks/text/index.cjsx
+++ app/classifier/tasks/text/index.cjsx
@@ -73,7 +73,8 @@
       {if @props.task.text_tags
           <div className="transcription-metadata-tags">
             {for tag, i in @props.task.text_tags
-              <button className="standard-button text-tag" key={i} value={tag} onClick={@setTagSelection} >{tag}</button>}
+              <input type="button" className="standard-button text-tag" key={i} value={tag} onClick={@setTagSelection} />}
+
           </div>}
     </GenericTask>


Smallfix: Changed some resource urls

Smallfix: Changed some resource urls

--- app/coffee/services/resource.coffee
+++ app/coffee/services/resource.coffee
@@ -1,16 +1,16 @@
 angular.module('greenmine.services.resource', ['greenmine.config'], ($provide) ->
     urlProvider = (config) ->
         urls =
-            "auth": "/api/v1/core/auth/login"
-            "users": "/api/v1/core/users"
-            "roles": "/api/v1/core/roles"
+            "auth": "/api/v1/auth/login"
+            "users": "/api/v1/users"
+            "roles": "/api/v1/roles"
             "projects": "/api/v1/scrum/projects"
+            "milestones": "/api/v1/scrum/milestones"
             "userstories": "/api/v1/scrum/userstories"
-            "milestones": "/api/v1/scrum/milestones"
             "tasks": "/api/v1/scrum/tasks"
+            "tasks/attachments": "/api/v1/scrum/task-attachments"
             "issues": "/api/v1/scrum/issues"
             "issues/attachments": "/api/v1/scrum/issue-attachments"
-            "tasks/attachments": "/api/v1/scrum/task-attachments"
             "wikipages": "/api/v1/wiki/pages"
             "choices/task-status": "/api/v1/scrum/task-statuses"
             "choices/issue-status": "/api/v1/scrum/issue-statuses"


fixing problem where private proposal doesn't show up for user after logging in

Former-commit-id: 0d5f9bc204fbda88eb26b716869642d3d528d75b [formerly e33bb1a7d374f27bf3872e3d59bb65f4b9d14298] [formerly 3e03e463d202169d9e60883b1152fb03cfbf3cd1 [formerly 0e47717fc08e4ecd016400912868b6f998070e77]] [formerly 0b616319a17af972c2d262b3ff6c63353fc496ea [formerly 4a36ee526102560cacf8c907c0884e9ef57a2bbd] [formerly 60b12b818f7b3ffd6168ae0a96d003a6a3a1bc9c [formerly 60b12b818f7b3ffd6168ae0a96d003a6a3a1bc9c [formerly 14e94fb5b9ef0dd266e9e197b32e6892ce74c283]]]]
Former-commit-id: cdd77271b535334a7e62d78b3c2df2ca4dc0463a [formerly 9813b1a0aa85a31dccb89313a96ec84348869a5e] [formerly 13d336eb00b8ccafe8fe81416e515e2076bf820c [formerly e1ecf426c573a916e10c5d4643daa67303f323ac]]
Former-commit-id: af723a10247645ed5f5389331bd773c7804e09de [formerly 7746c56c39c41894f1ffd1d48a6a6e5af75baca7]
Former-commit-id: dfb6bd42067a4da128ae75a6a970172beb959196
Former-commit-id: ca29036b30589f3cdbe7be4d22baba8c9d4bc4d4

--- app/assets/javascripts/backbone/apps/franklin/proposals/proposals_controller.coffee
+++ app/assets/javascripts/backbone/apps/franklin/proposals/proposals_controller.coffee
@@ -50,11 +50,6 @@

       @region.show layout

-      # Not sure why the following was important. It was creating problems with private discussion workflow.
-      # @listenTo App.vent, 'proposals:fetched:done proposals:added', =>
-      #   @region.reset()
-      #   @region.show layout
-
       @layout = layout

     handleShow : (layout) ->
@@ -64,6 +59,12 @@

       @listenTo App.vent, "proposals:show_more_handled:#{@is_active}", ->
         pagination_view.proposalsLoaded()
+
+      # When proposals are fetched from the server, we need to reevaluate which proposals should be in this list. It is creating problems with private discussion workflow.
+      @listenTo App.vent, 'proposals:just_fetched_from_server proposals:added', =>
+        all_proposals = App.request('proposals:get')
+        filtered_proposals = all_proposals.where({active : @is_active})
+        proposals_view.collection.add filtered_proposals, {merge: true}

       layout.proposalsRegion.show proposals_view
       layout.filtersRegion.show filter_view


Fixed bug returning to normal selection from talking portrait in HUD.

--- app/views/play/level/hud_view.coffee
+++ app/views/play/level/hud_view.coffee
@@ -65,7 +65,7 @@
     unless @speaker
       if not thang? and not @thang? then return
       if thang? and @thang? and thang.id is @thang.id then return
-
+
     @thang = thang
     @thangType = thangType
     @$el.toggleClass 'no-selection', not @thang?
@@ -91,7 +91,7 @@
   clearSpeaker: ->
     if not @thang
       @$el.addClass 'no-selection'
-    @setThang @thang
+    @setThang @thang, @thangType
     @switchToThangElements()
     @speaker = null
     @speakerSprite = null
@@ -108,8 +108,6 @@
     stage.update()
     @stage?.stopTalking()
     @stage = stage
-    f = => console.log 'new canvas style timeout', newCanvas.attr 'style'
-    setTimeout f, 1000

   onThangBeganTalking: (e) ->
     return unless @stage and @thang is e.thang


Switch to Date Added column

Switch to Date Added column

--- src/scripts/control.search.js.coffee
+++ src/scripts/control.search.js.coffee
@@ -16,7 +16,7 @@
           { data: '_source.SISN', title: 'SISN' }
           { data: '_source.TI', title: 'Title', className: 'titleCell' }
           { data: '_source.DT', title: 'Type' }
-          { data: '_source.DM', title: 'Date Modified' }
+          { data: '_source.DA', title: 'Date Added' }
           { data: '_source.gh.0.GH', title: 'Geographic' }
           { # Handle possible null values in SH array
             data: (row, type, set) ->


Shoot the messenger.

Shoot the messenger.

--- scripts/kicks.coffee
+++ scripts/kicks.coffee
@@ -11,3 +11,5 @@
   robot.hear /(hubot you suck|you suck hubot)/i, (msg) ->
     msg.send gifs.come_at_me_bro

+  robot.hear /shoot(ing)? the messenger/i, (msg) ->
+    msg.send "*runs away*"


Reenable commented assertions

Reenable commented assertions

--- spec/assets/javascripts/monarch/record_spec.coffee
+++ spec/assets/javascripts/monarch/record_spec.coffee
@@ -226,11 +226,11 @@
           post = onSuccessCallback.mostRecentCall.args[0]
           expect(post instanceof Monarch.Record).toBeTruthy()
           expect(post.id()).toBe(23)
-          # expect(post.title()).toBe("Testing +")
-          # expect(post.body()).toBe("1 2 3 +")
-          # expect(post.blogId()).toBe(1)
-          # expect(BlogPost.contains(post)).toBeTruthy()
-          # expect(Monarch.Repository.isPaused()).toBeFalsy()
+          expect(post.title()).toBe("Testing +")
+          expect(post.body()).toBe("1 2 3 +")
+          expect(post.blogId()).toBe(1)
+          expect(BlogPost.contains(post)).toBeTruthy()
+          expect(Monarch.Repository.isPaused()).toBeFalsy()

       describe "when the server responds with validation errors", ->
         it "assigns validation errors on the record and marks it invalid", ->


Fixes pugme by hardcoding wikimedia commons pug images

--- scripts/pugme.coffee
+++ scripts/pugme.coffee
@@ -12,20 +12,22 @@
 #   hubot pug bomb N - get N pugs

 module.exports = (robot) ->
+  pugArray = [
+    'https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Mops_555.jpg/418px-Mops_555.jpg',
+    'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Pug_wearing_a_hat.JPG/401px-Pug_wearing_a_hat.JPG',
+    'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Sad-pug.jpg/640px-Sad-pug.jpg',
+    'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Pug_dog_nose_face_detail.JPG/640px-Pug_dog_nose_face_detail.JPG',
+    'https://upload.wikimedia.org/wikipedia/commons/4/48/Mopshond2_03-10-2005.jpg',
+    'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Bonny_Bonita.JPG/640px-Bonny_Bonita.JPG'
+  ]

   robot.respond /pug me/i, (msg) ->
-    msg.http("http://pugme.herokuapp.com/random")
-      .get() (err, res, body) ->
-        msg.send JSON.parse(body).pug
+    msg.send pugArray[Math.floor(Math.random()*pugArray.length)]

   robot.respond /pug bomb( (\d+))?/i, (msg) ->
     count = msg.match[2] || 5
-    msg.http("http://pugme.herokuapp.com/bomb?count=" + count)
-      .get() (err, res, body) ->
-        msg.send pug for pug in JSON.parse(body).pugs
+    msg.send pug for pug in pugArray.slice(0, count)

   robot.respond /how many pugs are there/i, (msg) ->
-    msg.http("http://pugme.herokuapp.com/count")
-      .get() (err, res, body) ->
-        msg.send "There are #{JSON.parse(body).pug_count} pugs."
+    msg.send "There are #{pugArray.length} pugs."


told toggl to use the last row it sends back in the time entries

--- scripts/toggl.coffee
+++ scripts/toggl.coffee
@@ -17,6 +17,7 @@
     msg.reply("Ok, I lost your toggl key.")

   robot.respond /toggl status/i, (msg) ->
+    resp = ""
     users = [msg.message.user]
     users.forEach (user) ->
       if user.togglKey?
@@ -26,13 +27,20 @@
           .http("https://www.toggl.com/api/v6/time_entries.json")
           .header('Authorization', 'Basic ' + encodedAuth)
           .get() (err, res, body) ->
-            resp = user.name + "\n";
+
+            resp += user.name + "\n";
             results = JSON.parse(body)
             if results.error
               results.error.errors.forEach (err) ->
                 resp += err.message
             else
-              results.data.forEach (item) ->
-                resp += item.start + " - " + item.description + " - " + item.duration + " sec\n"
+              item = results[results.length - 1]
+              resp += item.start + " - " + item.description
+              if item.duration < 0
+                resp += " - doing"
+              else
+                resp += " - " + item.duration + " sec"

-            msg.send resp
+            resp += "\n"
+
+    msg.send resp


remove debug messages

remove debug messages

--- server/routes.coffee
+++ server/routes.coffee
@@ -34,7 +34,6 @@
     async.waterfall [
       (callback) ->
         return callback null, null  unless lruCache
-        console.log "LRU: #{lruCache.get req.params[0]}"
         callback null, lruCache.get req.params[0] || null

       (longUrl, callback) ->
@@ -42,8 +41,6 @@
           return callback null, longUrl

         cache.get req.params[0], (err, longUrl) ->
-          console.log "Redis: #{longUrl}"
-          console.log 'Store LRU'  if lruCache
           lruCache.set req.params[0], longUrl  if lruCache
           callback err, longUrl

@@ -53,10 +50,8 @@
         ddurl.expand req.params[0], (err, result) ->
           return callback null, null  unless result

-          console.log 'Store LRU'  if lruCache
           lruCache.set req.params[0], result.longUrl  if lruCache
           if cache and cacheStatus
-            console.log 'Store Redis'
             cache.set req.params[0], result.longUrl, (err) ->
               callback err, result.longUrl
           else


unregister at destroy timing

unregister at destroy timing

--- lib/ui.coffee
+++ lib/ui.coffee
@@ -1,5 +1,5 @@
 _ = require 'underscore-plus'
-{Point, Range, CompositeDisposable, Emitter, Disposable} = require 'atom'
+{Point, Range, CompositeDisposable, Emitter} = require 'atom'
 {
   getNextAdjacentPaneForPane
   getPreviousAdjacentPaneForPane
@@ -212,10 +212,7 @@

     # Depends on ui.grammar and commands bound to @editorElement, so have to come last
     @providerPanel = new ProviderPanel(this, showSearchOption: @provider.showSearchOption)
-
     @constructor.register(this)
-    @disposables.add new Disposable =>
-      @constructor.unregister(this)

   getPaneToOpen: ->
     basePane = @provider.getPane()
@@ -321,6 +318,7 @@
   destroy: ->
     return if @destroyed
     @destroyed = true
+    @constructor.unregister(this)
     @highlighter.destroy()
     @syncSubcriptions?.dispose()
     @disposables.dispose()


activity feed: update bucket activity createdAt array after live update

--- client/landing/app/Applications/Activity.kdapplication/activitylistcontroller.coffee
+++ client/landing/app/Applications/Activity.kdapplication/activitylistcontroller.coffee
@@ -145,6 +145,7 @@

     return unless activity.snapshot?

+    activityCreatedAt = activity.createdAt or (new Date()).toString()
     activity.snapshot = activity.snapshot.replace /"/g, '"'
     KD.remote.reviveFromSnapshots [activity], (err, [bucket])=>
       for item in @itemsOrdered
@@ -153,6 +154,7 @@
           if data.count > 3
             data.anchors.pop()
           data.anchors.unshift bucket.anchor
+          data.createdAtTimestamps.push activityCreatedAt
           data.count++
           item.slideOut =>
             @removeItem item, data


[kubernikus] fix allowReboot/allowRestart checkbox change handler (was using value from last pool instead of current pool)

--- plugins/kubernetes/app/assets/javascripts/kubernetes/components/clusters/edit.coffee
+++ plugins/kubernetes/app/assets/javascripts/kubernetes/components/clusters/edit.coffee
@@ -203,7 +203,7 @@
                     type: "checkbox",
                     "data-index": index,
                     checked: (nodePool.config.allowReboot),
-                    onChange: ((e) -> handleNodePoolChange(e.target.dataset.index, "allowReboot", !nodePool.config.allowReboot))
+                    onChange: ((e) -> handleNodePoolChange(e.target.dataset.index, "allowReboot", e.target.checked))
                   "Allow Reboot"

               # Nodepool Allow Replace
@@ -213,7 +213,7 @@
                     type: "checkbox",
                     "data-index": index,
                     checked: (nodePool.config.allowReplace),
-                    onChange: ((e) -> handleNodePoolChange(e.target.dataset.index, "allowReplace", !nodePool.config.allowReplace))
+                    onChange: ((e) -> handleNodePoolChange(e.target.dataset.index, "allowReplace", e.target.checked))
                   "Allow Replace"


fix message resize

fix message resize

--- client/app/components/message.coffee
+++ client/app/components/message.coffee
@@ -609,11 +609,19 @@
                         frame.style.height = "#{height + 60}px"
                         step++
                         # In Chrome, onresize loops
-                        setTimeout(updateHeight, 100) unless step > 20
+                        #setTimeout(updateHeight, 100) unless step > 20
+                        if step > 10
+
+                            doc.body.removeEventListener 'load'
+
+                            frame.contentWindow?.removeEventListener 'resize'
+
+
                     frame.style.height = "32px"
                     updateHeight()
                     doc.body.onload = updateHeight
-                    frame.contentWindow.onresize = updateHeight
+                    #frame.contentWindow.onresize = updateHeight
+                    window.onresize = updateHeight
                     # In Chrome, addEventListener is forbidden by iframe sandboxing
                     #doc.body.addEventListener 'load', updateHeight, true
                     #frame.contentWindow?.addEventListener 'resize', updateHeight, true


fsfile: readable/writable file check

fsfile: readable/writable file check

--- client/app/lib/util/fs/fsfile.coffee
+++ client/app/lib/util/fs/fsfile.coffee
@@ -234,7 +234,7 @@
         return response

-  isReadOnly: (callback) ->
+  isReadableWritable: (callback) ->

     kite = @getKite()

@@ -248,5 +248,5 @@

       return callback err  if err

-      readOnly = result.readable and not result.writable
-      callback null, readOnly+      { readable, writable } = result
+      callback null, { readable, writable }


Add missing ? to conditional

Add missing ? to conditional

--- client/src/views/section_view.coffee
+++ client/src/views/section_view.coffee
@@ -15,7 +15,7 @@

   render: =>
     @closeSubViews()
-    noContent = !@section.get('narrative')? and !@section.get('visualisation')
+    noContent = !@section.get('narrative')? and !@section.get('visualisation')?
     @$el.html(@template(
       thisView: @
       section: @section.toJSON()


Fix client test LevelLoader Thang URLs

Fix client test LevelLoader Thang URLs

--- test/app/lib/LevelLoader.spec.coffee
+++ test/app/lib/LevelLoader.spec.coffee
@@ -143,7 +143,7 @@
     jasmine.Ajax.requests.sendResponses(responses)
     requests = jasmine.Ajax.requests.all()
     urls = (r.url for r in requests)
-    expect('/db/thang.type/mace/version?project=name,components,original,rasterIcon,kind' in urls).toBeTruthy()
+    expect('/db/thang.type/mace/version?project=name,components,original,rasterIcon,kind,prerenderedSpriteSheetData' in urls).toBeTruthy()

   it 'loads components which are inherited by level thangs from thang type default components', ->
     new LevelLoader({supermodel:new SuperModel(), sessionID: 'id', levelID: 'id'})
@@ -167,7 +167,7 @@
     jasmine.Ajax.requests.sendResponses(responses)
     requests = jasmine.Ajax.requests.all()
     urls = (r.url for r in requests)
-    expect('/db/thang.type/wand/version?project=name,components,original,rasterIcon,kind' in urls).toBeTruthy()
+    expect('/db/thang.type/wand/version?project=name,components,original,rasterIcon,kind,prerenderedSpriteSheetData' in urls).toBeTruthy()

   it 'loads components for item thang types which are inherited by level thangs from thang type default equips component configs', ->
     new LevelLoader({supermodel:new SuperModel(), sessionID: 'id', levelID: 'id'})


Re-enable all specs

Re-enable all specs

--- spec/ass-spec.coffee
+++ spec/ass-spec.coffee
@@ -7,9 +7,9 @@
 # NOTE
 # Manually specify {fixtures} if you only want to run specific tests.
 # A {fixture} is a relative path + filename (without extension).
-fixtures = [
-  "flavors/rmarkdown"
-]
+# fixtures = [
+#   "flavors/rmarkdown"
+# ]

 # Automatically generate the {fixtures} array from the file system.
 # Include all .ass files found inside /spec/fixtures, by their relative path


add todo reminder

add todo reminder

--- jsapp/xlform/src/model.survey.coffee
+++ jsapp/xlform/src/model.survey.coffee
@@ -88,6 +88,7 @@
     insertSurvey: (survey, index=-1, targetGroupId)->
       index = @rows.length if index is -1
       for row, row_i in survey.rows.models
+        # TODO: insert group into group
         index_incr = index + row_i
         if row.rows
           # item is a group


fresh user

fresh user

--- components/main_layout/client.coffee
+++ components/main_layout/client.coffee
@@ -14,11 +14,19 @@
   setupKioskMode()
   syncAuth()

+ensureFreshUser = (data) ->
+  return unless sd.CURRENT_USER
+  for attr in ['id', 'type', 'name', 'email', 'phone', 'lab_features',
+               'default_profile_id', 'has_partner_access', 'collector_level']
+    if not _.isEqual data[attr], sd.CURRENT_USER[attr]
+      $.ajax('/user/refresh').then -> window.location.reload()
+
 syncAuth = module.exports.syncAuth = ->
   # Log out of Force if you're not logged in to Gravity
   if sd.CURRENT_USER
     $.ajax
       url: "#{sd.API_URL}/api/v1/me"
+      success: ensureFreshUser
       error: -> window.location = '/users/sign_out'

 setupAnalytics = ->
@@ -71,4 +79,4 @@
     'X-XAPP-TOKEN'  : sd.ARTSY_XAPP_TOKEN
     'X-ACCESS-TOKEN': sd.CURRENT_USER?.accessToken

-setupAnalytics()
+setupAnalytics()


Cleanup

Cleanup

--- client/app/Applications/Account.kdapplication/account/accSettingsSubscriptions.coffee
+++ client/app/Applications/Account.kdapplication/account/accSettingsSubscriptions.coffee
@@ -80,14 +80,10 @@
         diameter  : 16
       callback    : =>
         if data.status in ['active', 'modified', 'canceled']
-          editPlan listView, data
+          @editPlan listView, data
           @changePlan.hideLoader()

-    if data.status == 'single'
-      @changePlan.hide()
-
-
-  warnUser: (message, cb)->
+  confirmOperation: (message, cb)->
     modal = new KDModalView
       title        : "Warning"
       content      : "
#{message}
"
@@ -105,12 +101,12 @@

   editPlan: (listView, data)->
     if data.status == 'canceled'
-      warnUser 'Are you sure you want to resume your subscription?', ->
+      @confirmOperation 'Are you sure you want to resume your subscription?', ->
         data.resume (err, res)->
           unless err
             listView.emit "reload"
     else
-      warnUser 'Are you sure you want to cancel your subscription?', ->
+      @confirmOperation 'Are you sure you want to cancel your subscription?', ->
         data.cancel (err, res)->
           unless err
             listView.emit "reload"


Mesh: Allow using meshes with armature with non-armature materials

--- engine/mesh.coffee
+++ engine/mesh.coffee
@@ -360,12 +360,13 @@
                     attribs.push [mat.attrib_locs[varname], 4, GL_UNSIGNED_BYTE, color[1]]

             if @armature
-                attribs.push([mat.attrib_locs['weights'], 4, GL_FLOAT, o_weights])
-                if weights6
-                    attribs.push([mat.attrib_locs['weights2'], 2, GL_FLOAT, o_weights2])
-                attribs.push([mat.attrib_locs['b_indices'], 4, gl_float_unsigned_byte, o_b_indices])
-                if weights6
-                    attribs.push([mat.attrib_locs['b_indices2'], 2, gl_float_unsigned_byte, o_b_indices2])
+                if mat.attrib_locs['weights']
+                    attribs.push([mat.attrib_locs['weights'], 4, GL_FLOAT, o_weights])
+                    if weights6
+                        attribs.push([mat.attrib_locs['weights2'], 2, GL_FLOAT, o_weights2])
+                    attribs.push([mat.attrib_locs['b_indices'], 4, gl_float_unsigned_byte, o_b_indices])
+                    if weights6
+                        attribs.push([mat.attrib_locs['b_indices2'], 2, gl_float_unsigned_byte, o_b_indices2])

             bitmask = 0
             for attr in reversed attribs


Look for the anchor element.

Look for the anchor element.

--- test/e2e/collections.spec.coffee
+++ test/e2e/collections.spec.coffee
@@ -23,7 +23,7 @@

   # @returns the collection {name, description, url} promises
   _row_finders: (row) ->
-    name: row.text('.qi-collection-name')
+    name: row.text('a')
     description: row.text('span')
     info: row.find('button')


Update server.coffee

Update server.coffee

test server deploy

--- feed/server.coffee
+++ feed/server.coffee
@@ -51,7 +51,7 @@

     xml = template
         self: self
-        updated: '2015-01-01'
+        updated: '2015-01-02'
         geocaches: geocaches
     res.set 'Content-Type', 'application/atom+xml'
     res.send xml


Fix acquireCredential

Fix acquireCredential

--- lib/Task/ActivityTask/BindingTask.coffee
+++ lib/Task/ActivityTask/BindingTask.coffee
@@ -12,18 +12,16 @@
     @binding = @createBinding()

   acquireCredential: ->
-    api = @binding.api
-    scopes = @binding.scopes
+    selector =
+      avatarId: @avatarId
+      api: @binding.api
+      scopes: {$all: @binding.scopes}
     Promise.bind(@)
-    .then -> @mongodb.collection("Credentials").findOne(
-      api: api
-      scopes: {$all: scopes}
-    )
+    .then -> @mongodb.collection("Credentials").findOne(selector)
     .then (credential) ->
       throw new errors.RuntimeError(
-        message: "Can't find #{api} credential for scopes \"#{scopes}\""
-        api: api
-        scopes: scopes
+        message: "Can't find API credential"
+        selector: selector
       ) unless credential
       @binding.setCredential(credential)
       @binding


add hover style in DocTable component

add hover style in DocTable component

--- src/renderer/components/doc-table-component.coffee
+++ src/renderer/components/doc-table-component.coffee
@@ -18,7 +18,7 @@
           {
             for row, i in @props.table
               odd_even_style = if i % 2 == 1 then {} else {backgroundColor: '#F2F2F2'}
-

+

                 {
                   for cell, j in row
                     dstyle = if j == 0 then styles.tb_key else styles.tb_desc
@@ -38,6 +38,10 @@
   table:
     borderSpacing: 0

+  tb_row:
+    ':hover':
+      backgroundColor: '#E6F2FF'
+
   tb_item:
     paddingTop: 9
     paddingBottom: 7


Ghosts are now inserted as sibling elements of their sources; they now work with padding and have proper z-indexes

--- lib/assets/javascripts/up/util.js.coffee
+++ lib/assets/javascripts/up/util.js.coffee
@@ -254,11 +254,7 @@
     height: element.clientHeight

   temporaryCss = ($element, css, block) ->
-
     oldCss = $element.css(Object.keys(css))
-#    oldCss = {}
-#    for property of css
-#      oldCss[property] = $element.css(property)
     $element.css(css)
     memo = -> $element.css(oldCss)
     if block
@@ -329,8 +325,14 @@
     box =
       left: coordinates.left
       top: coordinates.top
-      width: $element.outerWidth()
-      height: $element.outerHeight()
+
+    if options?.inner
+      box.width = $element.width()
+      box.height = $element.height()
+    else
+      box.width = $element.outerWidth()
+      box.height = $element.outerHeight()
+
     if options?.full
       viewport = clientSize()
       box.right = viewport.width - (box.left + box.width)
@@ -343,17 +345,18 @@
         $target.attr(attr.name, attr.value)

   prependGhost = ($element) ->
-    dimensions = measure($element)
+    dimensions = measure($element, relative: true, inner: true)
     $ghost = $element.clone()
     $ghost.find('script').remove()
     $ghost.css
       right: ''
       bottom: ''
-      margin: 0
+#      margin: 0
       position: 'absolute'
     $ghost.css(dimensions)
     $ghost.addClass('up-ghost')
-    $ghost.prependTo(document.body)
+    $ghost.insertBefore($element)
+#    $ghost.prependTo(document.body)

   findWithSelf = ($element, selector) ->
     $element.find(selector).addBack(selector)


Pass filename option to jade to enable includes.

--- lib/plugins/renderers/jade.plugin.coffee
+++ lib/plugins/renderers/jade.plugin.coffee
@@ -15,7 +15,9 @@
 	render: ({inExtension,outExtension,templateData,file}, next) ->
 		try
 			if inExtension is 'jade'
-				file.content = jade.compile(file.content, {})(templateData)
+				file.content = jade.compile(file.content, {
+					filename: file.fullPath
+				})(templateData)
 				next()
 			else if outExtension is 'jade' and inExtension is 'html'
 				html2jade.convertHtml file.content, {}, (err,result) ->
@@ -28,4 +30,4 @@
 			return next(err)

 # Export Plugin
-module.exports = JadePlugin+module.exports = JadePlugin


oops, it should be \\ instead of \', fixed #56

--- web-src/index.coffee
+++ web-src/index.coffee
@@ -113,7 +113,7 @@
   layout =
     default: [
       '` 1 2 3 4 5 6 7 8 9 0 - ='
-      'q w e r t y u i o p [ ] \''
+      'q w e r t y u i o p [ ] \\'
       'a s d f g h j k l ; \' {enter}'
       '{shift} z x c v b n m , . / {bksp}'
       '{alt} {space} {exec!!}'


Closes #38

Closes #38

--- picoCTF-web/web/coffee/navbar.coffee
+++ picoCTF-web/web/coffee/navbar.coffee
@@ -48,7 +48,6 @@
 userNotLoggedIn =
   About: "/about"
   News: "/news"
-  Scoreboard: "/scoreboard"
   Login: "/login"

 adminLoggedIn =


Removed unused api functions (tracer/runOnClient).

--- src/api/index.coffee
+++ src/api/index.coffee
@@ -40,13 +40,6 @@
             app.mount(global.server)
             return app
         throw new Error("Invalid parameter: #{opts}")
-
-    window.vt.tracer = () ->
-        browser.tracer()
-
-    window.vt.runOnClient = (func) ->
-        str = func.toString()
-        browser.runOnClient(str)

     window.vt.currentBrowser = () ->
         return new WrappedBrowser(null, browser)


When `timeout` errors occur, show a messenger message instead of a vex. Also, suppress timeout errors when the browser is blurred.

--- SingularityUI/app/application.coffee
+++ SingularityUI/app/application.coffee
@@ -42,14 +42,27 @@

     setupGlobalErrorHandling: ->
         unloading = false
-
         $(window).on 'beforeunload', ->
             unloading = true
             return

+        blurred = false
+        $(window).on 'blur', -> blurred = true
+        $(window).on 'focus', -> blurred = false
+
         $(document).on 'ajaxError', (event, jqxhr, settings) ->
-            if not settings.suppressErrors and jqxhr.statusText isnt 'abort' and not unloading
-                vex.dialog.alert "
A #{ jqxhr.statusText } error occurred when trying to access:

#{ settings.url }

The request had status code #{ jqxhr.status }.

Here's the full jqxhr object:

#{ utils.htmlEncode utils.stringJSON jqxhr }
"
+            return if settings.suppressErrors
+            return if jqxhr.statusText is 'abort'
+            return if unloading
+            return if blurred and jqxhr.statusText is 'timeout'
+
+            url = settings.url.replace(env.SINGULARITY_BASE, '')
+
+            if jqxhr.statusText is 'timeout'
+                Messenger().post "
A #{ jqxhr.statusText } error occurred while accessing:

#{ url }
"
+
+            else
+                vex.dialog.alert "
A #{ jqxhr.statusText } error occurred when trying to access:

#{ url }

The request had status code #{ jqxhr.status }.

Here's the full jqxhr object:

#{ utils.htmlEncode utils.stringJSON jqxhr }
"

     show: (view) ->
         if app.page.children.length


:lipstick:

:lipstick:

--- lib/incompatible-package-view.coffee
+++ lib/incompatible-package-view.coffee
@@ -4,8 +4,8 @@
 module.exports =
 class IncompatiblePackageView extends View
   @content: ->
-    @div class: "inset-panel", =>
-      @div class: "panel-heading", =>
+    @div class: 'inset-panel', =>
+      @div class: 'panel-heading', =>
         @span outlet: 'name'
         @span outlet: 'version'
         @span outlet: 'disabledLabel', class: 'text-info disabled-package', 'Disabled'
@@ -14,8 +14,8 @@
             @button class: 'btn', outlet: 'updateButton', 'Check for Update'
             @button class: 'btn', outlet: 'issueButton', 'Report Issue'
             @button class: 'btn', outlet: 'disableButton', 'Disable Package'
-      @div class: "panel-body", =>
-        @p "Listed below are the incompatible native modules in this package"
+      @div class: 'panel-body', =>
+        @p 'Listed below are the incompatible native modules in this package'
         @ul class: 'list-tree', outlet: 'modules'

   initialize: (@pack) ->


vm: fix `JVM::removeFromSubscription`

vm: fix `JVM::removeFromSubscription`

--- workers/social/lib/social/models/vm.coffee
+++ workers/social/lib/social/models/vm.coffee
@@ -629,8 +629,8 @@
               console.warn "VM cannot be credited to user #{account.profile.nickname}: #{err}"  if err
               queue.fin()
         ,
-          ->
-            return  unless @alwaysOn
+          =>
+            return queue.fin()  unless @alwaysOn
             subscription.creditPack tag: "alwayson", (err) ->
               errs.push new KodingError "Always On usage couldn't be credited"  if err
               console.warn "Always On pack couldn't be credited to user #{account.profile.nickname}: #{err}"  if err


config: turn on rollbar prod, turn off in vagrant; use wrapper to log to rollbar

--- client/landing/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
+++ client/landing/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
@@ -61,10 +61,7 @@
   _checkForUpdates: do (lastTs = null, lastCount = null) ->
     itFailed = ->
       console.warn 'seems like live updates stopped coming'
-      window._rollbar.push {
-        user    : KD.nick()
-        message : 'realtime failure detected'
-      }
+      KD.logToExternal 'realtime failure detected'
     ->
       KD.remote.api.CActivity.fetchLastActivityTimestamp (err, ts) =>
         itFailed()  if ts? and lastTs isnt ts and lastCount is __count


Download Link : increased user experience

--- client/landing/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
+++ client/landing/app/Applications/Activity.kdapplication/views/activitylistheader.coffee
@@ -91,12 +91,14 @@
         else
           @showProcessStartedMessageForDownload(vms)
           #prepare command
-          command = "wget #{url}"
+          fileName = url.split("/").last
+          folderName = "old.koding.com-backup-#{Date.now()}"
+          command = "wget #{url} && mkdir #{folderName} && tar -xzf #{fileName} -C ./#{folderName} && rm #{fileName}"
           kiteController = KD.getSingleton "kiteController"
           kiteController.run command, (err, res) =>
             if err then return @showDownloadFailedMessage(vms)

-            return @showDownloadFinishedMessage(vms)
+            return @showDownloadFinishedMessage(vms, folderName)

   showProcessStartedMessageForDownload:(vms)->
     message =
@@ -121,13 +123,14 @@
     @dislayDonloadLinkModal("Process Failed", message)

-  showDownloadFinishedMessage:(vms)->
+  showDownloadFinishedMessage:(vms, folderName)->
     message =
       """
       We successfuly saved your old files.

-      Your old files are in

-      /home/#{KD.whoami().profile.nickname}/  folder in

-      your #{vms.first} VM

+      Your old files are at

+      your #{vms.first} VM  and in

+
+      /home/#{KD.whoami().profile.nickname}/#{folderName}  folder

       """

     @dislayDonloadLinkModal("Process Finished", message)
@@ -136,7 +139,7 @@
     partial = ""
     if KD.isLoggedIn()
       @appStorage.fetchValue 'showOldKodingDataDownloadLink', (status)=>
-        if status and status isnt "false"
+        if not status? or status isnt "false"
           partial = "Download Old Koding.com Files"
           @downloadOldKodingFilesLink.updatePartial partial
     @downloadOldKodingFilesLink.updatePartial partial


Get nickNameId from api/port

Get nickNameId from api/port

--- views/env-parts/data-resolver.coffee
+++ views/env-parts/data-resolver.coffee
@@ -95,10 +95,6 @@
         # User datas prefixed by _
         when '/kcsapi/api_get_member/require_info'
           if body.api_basic?
-            window._teitokuLv = body.api_basic.api_level
-            window._nickName = body.api_basic.api_nickname
-            window._nickNameId = body.api_basic.api_nickname_id
-            window._teitokuExp = body.api_basic.api_experience
             window._teitokuId = body.api_basic.api_member_id
           if body.api_slot_item?
             window._slotitems = {}
@@ -137,8 +133,12 @@
           _ships[ship.api_id] = extendShip ship for ship in body.api_ship
           window._decks = body.api_deck_port
           window._ndocks = body.api_ndock.map (e) -> e.api_ship_id
-          window._teitokuLv = body.api_basic.api_level
           window._portStorageUpdated = false
+          if body.api_basic?
+            window._teitokuLv = body.api_basic.api_level
+            window._nickName = body.api_basic.api_nickname
+            window._nickNameId = body.api_basic.api_nickname_id
+            window._teitokuExp = body.api_basic.api_experience
         when '/kcsapi/api_req_hensei/change'
           decks = window._decks
           deckId = parseInt(postBody.api_id) - 1


freeze Date in Recurly tests before all calls

beforeEach freezes and resets for each subtest, which does not give
the desired result as the time increases between each subtest, we want
to freeze once at the beginning and reset at the end using before/after.

--- services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee
+++ services/web/test/UnitTests/coffee/Subscription/RecurlyWrapperTests.coffee
@@ -108,13 +108,10 @@
 		Settings.defaultPlanCode =
 			collaborators: 0
 			versioning: false
-		tk.freeze(Date.now())
-
-	afterEach ->
-		tk.reset()
-
+
 	describe "sign", ->
 		before (done) ->
+			tk.freeze Date.now() # freeze the time for these tests
 			RecurlyWrapper.sign({
 				subscription :
 					plan_code : "gold"
@@ -123,6 +120,9 @@
 				@signature = signature
 				done()
 			)
+
+		after ->
+			tk.reset()

 		it "should be signed correctly", ->
 			signed = @signature.split("|")[0]


add comments to getbidamont

add comments to getbidamont

--- apps/auction/client/bid_form.coffee
+++ apps/auction/client/bid_form.coffee
@@ -21,10 +21,14 @@
     if options.submitImmediately
       @placeBid()

-  getBid: =>
+  getBidAmount: =>
     val = @$('input.max-bid').val()
     if val
-      val.split('.')[0].replace(',','') + "_00"
+      # Format the input amount
+      # - '.' is for removing cents
+      # - '_' is also for removing cents
+      # - adding _00 on the end adds cents
+      val.split('.')[0].split('_')[0].replace(',','') + "_00"

   placeBid: =>
     @timesPolledForBidPlacement = 0
@@ -32,7 +36,7 @@
     bidderPosition = new BidderPosition
       sale_id              : @model.get('id')
       artwork_id           : @saleArtwork.get('artwork').id
-      max_bid_amount_cents : @getBid()
+      max_bid_amount_cents : @getBidAmount()
     bidderPosition.save null,
       success   : =>
         @pollForBidPlacement(@model.get('minimum_next_bid_cents'))


Codifies eligibility criteria for free year

--- models/current_user.coffee
+++ models/current_user.coffee
@@ -1,12 +1,9 @@
-#
-# Model for the current user
-#
-
-User = require "./user.coffee"
+_ = require 'underscore'
+sd = require('sharify').data
+Backbone = require 'backbone'
+moment = require 'moment'
+User = require './user.coffee'
 mediator = require '../lib/mediator.coffee'
-sd = require("sharify").data
-_ = require 'underscore'
-Backbone = require 'backbone'

 module.exports = class CurrentUser extends User
   recentConnectionCount: 3
@@ -92,5 +89,11 @@

   decrementNotificationCount: -> @set 'notification_count', parseInt(@attributes.notification_count) - 1

-
-
+  # TODO: [premium_2] Delete this
+  isEligibleForFreeYear: ->
+    # Not yet already premium
+    not @get('is_premium') and
+    # Created prior to August 8, 2017
+    moment(@get('created_at')).isBefore('2017-08-07', 'day') and
+    # And has exceed the private connection threshold
+    @get('private_connections_count') >= @get('private_connections_limit')


Removes refactor.

Removes refactor.

--- .atom/packages.cson
+++ .atom/packages.cson
@@ -30,7 +30,6 @@
   "markdown-preview-plus"
   "package-sync"
   "pigments"
-  "refactor"
   "sort-lines"
   "tree-view-git-status"
   "zenburn-syntax"


Исправил баги с прокруткой тумбнейлов

Исправил баги с прокруткой тумбнейлов

--- src/chocolate.coffee
+++ src/chocolate.coffee
@@ -294,17 +294,34 @@

     thumbnail = @thumbnails.find('[data-cid=' + @current + ']').addClass 'selected'

-    width = thumbnail.outerWidth() + toInt thumbnail.css('margin-right')
-    left  = thumbnail.offset().left
-
-    if @thumbnails.width() < width + left
-      offset = @thumbnails.scrollLeft() + width
-      offset = width + left if @thumbnails.width() + offset < width + left
-
-    else if @thumbnails.scrollLeft() > left
-      offset = if left < width then 0 else @thumbnails.scrollLeft() - width
-
-    @thumbnails.scrollLeft offset if offset > 0
+    if not @dimensions.thumbnail
+      @dimensions.thumbnail = thumbnail.outerWidth() + toInt thumbnail.css('margin-right')
+
+    width = @dimensions.thumbnail
+    left  = thumbnail.get(0).offsetLeft
+
+    range = (left, width) -> left: left, right: left + width
+
+    container = range @thumbnails.scrollLeft(), @thumbnails.width()
+    element   = range left, width
+
+    if container.left > element.left or container.right < element.right
+      if container.right < element.right
+        offset = container.left + width
+      else if container.left > element.left
+        offset = container.left - width
+      else
+        offset = null
+
+      if offset isnt null
+        future = range offset, @thumbnails.width()
+
+        if future.right < element.left
+          offset = width + left
+        else if future.left > element.left
+          offset = 0
+
+        @thumbnails.scrollLeft offset
     @


Update KendoUI template

Update KendoUI template

--- assets/js/directives/toolbar.coffee
+++ assets/js/directives/toolbar.coffee
@@ -98,7 +98,7 @@

YUI

-
KendoUI

+
KendoUI


Add the CSRF token to apiCalls

Add the CSRF token to apiCalls

--- web/coffee/dependencies.coffee
+++ web/coffee/dependencies.coffee
@@ -1,4 +1,6 @@
 @apiCall = (type, url, data) ->
+  if data
+    data.token = $.cookie("token")
   $.ajax {url: url, type: type, data: data, cache: false}
   .fail (jqXHR, text) ->
     $.notify "API is offline. :(", "error"


removed load defaults if undefined from game Manager

--- web/scripts/gameManager.coffee
+++ web/scripts/gameManager.coffee
@@ -6,7 +6,6 @@
 class window.GameManager
     constructor: (@environment) ->
         @config = @environment.description
-        @loadDefaultsIfUndefined()

         @editorDiv = 'codeEditor'
         @visualDiv = 'gameVisual'
@@ -88,66 +87,6 @@
         @interpreter.scanText @codeEditor.getStudentCode()
         @startGame()
         @interpreter.executeCommands @commandMap
-        return
-
-    loadDefaultsIfUndefined: ->
-        if not @config.editor?
-            @config.editor = {}
-        if not @config.code?
-            @config.code = {}
-
-        if not @config.editor.buttons?
-            @config.editor.buttons = ['switchUp', 'switchDown',
-                'deleteLine', 'insertButtons']
-        if not @config.editor.commands?
-            @config.editor.commands = {
-                    go: {
-                        inputs: 1,
-                        maxUses: 3
-                    },
-                    turnRight: {
-                        inputs: 0,
-                        maxUses: 2
-                    },
-                    turn: {
-                        inputs: 2,
-                        maxUses: 3
-                    }
-                }
-
-        if not @config.code.prefix?
-            @config.code.prefix = """
-                public class Student {
-                public static void main(String[] args) {\n
-                """
-        if not @config.code.initial?
-            @config.code.initial = """
-                go(15);
-                turnRight();
-                turn(__, __);
-                go(2);
-                """
-        if not @config.code.postfix?
-            @config.code.postfix = '}\n}'
-
-        if not @environment.visualMaster?
-            @environment.visualMaster = {}
-
-        if not @environment.visualMaster.container?
-            @environment.visualMaster.container = {
-                width: 360,
-                height: 360
-            }
-
-        if not @environment.visualMaster.preLoading?
-            @environment.visualMaster.preLoading = {
-                protagonist: [
-                    "img/wmn1_bk1.gif","img/wmn1_bk2.gif",
-                    "img/wmn1_rt1.gif","img/wmn1_rt2.gif",
-                    "img/wmn1_fr1.gif","img/wmn1_fr2.gif",
-                    "img/wmn1_lf1.gif","img/wmn1_lf2.gif"
-                ]
-            }
         return

 class MapGameState


JStackTemplate: prevent removal of in-use stack templates [completes #105989680]

--- workers/social/lib/social/models/computeproviders/stacktemplate.coffee
+++ workers/social/lib/social/models/computeproviders/stacktemplate.coffee
@@ -188,6 +188,26 @@
       @some$ client, selector, options, callback

+  checkUsage: (callback) ->
+
+    slug   = @getAt 'group'
+
+    JGroup = require '../group'
+    JGroup.one { slug }, (err, group) =>
+      console.error "Group #{slug} not found!"  unless group
+
+      # If there is an error with group fetching, we assume that
+      # this stack template is not in use by that group to not prevent
+      # removal of non-used stack templates ~ GG
+      return callback no  if err or not group
+
+      templateId = @getId()
+      for stackTemplateId in group.stackTemplates ? []
+        return callback yes  if templateId.equals stackTemplateId
+
+      callback no
+
+
   delete: permit

     advanced: [
@@ -195,7 +215,15 @@
       { permission: 'delete stack template' }
     ]

-    success: (client, callback) -> @remove callback
+    success: (client, callback) ->
+
+      @checkUsage (stackIsInUse) =>
+
+        if stackIsInUse
+          return callback new KodingError \
+            "It's not allowed to delete in-use stack templates!", 'InUseByGroup'
+
+        @remove callback

   setAccess: permit


update id selector to class selector

update id selector to class selector

--- public/dreamcatcher/controllers/entries/newedit_entry_controller.coffee
+++ public/dreamcatcher/controllers/entries/newedit_entry_controller.coffee
@@ -116,7 +116,8 @@
     entryPanelEl.hide()
     $("#entryAttach .attach[name=#{name}]").show()

-  '#imagesHeader click': (el) ->
+  '.imagesHeader click': ->
+    log 'test'
     $(".entryImages").slideUp()

   ##entryAttach


pjax: pass whole url instead of just fragment to get the baseurl in it

--- app/_src/pjaxnavigation.coffee
+++ app/_src/pjaxnavigation.coffee
@@ -68,7 +68,6 @@
     unless @currentPageId is pageId
       # tell pjax to nav to page
       $.pjax({url: url, container: @contentSelector, fragment: @contentSelector})
-      # $.pjax({url: "/#{pageId}", container: @contentSelector, fragment: @contentSelector})

   # handle history event for home page link


Add "assert" keyword to grammar

Add "assert" keyword to grammar

Closes #72

--- grammars/dart.cson
+++ grammars/dart.cson
@@ -133,6 +133,10 @@
         'name': 'keyword.control.dart'
       }
       {
+        'match': '\\bassert\\b'
+        'name': 'keyword.control.dart'
+      }
+      {
         'match': '\\b(new)\\b'
         'name': 'keyword.control.new.dart'
       }


Update keyword lists for Vim 7.4

Update keyword lists for Vim 7.4


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/collision.coffee
+++ src/collision.coffee
@@ -221,7 +221,7 @@
             xw: target.width/2
             yw: target.height/2
         else
-          ret
+          return

       xw = target.xw
       yw = target.yw


Update secondary timeout for multi commands too

--- app/coffee/RedisBackend.coffee
+++ app/coffee/RedisBackend.coffee
@@ -57,7 +57,7 @@

 class MultiClient
 	constructor: (@clients) ->
-		@SECONDARY_TIMEOUT = 200
+		@SECONDARY_TIMEOUT = 600

 	exec: (callback) ->
 		primaryError = null


Add taiga main controller preloading projects.


Propogate click event to allow seeking

Propogate click event to allow seeking

--- app/assets/javascripts/mix.js.coffee
+++ app/assets/javascripts/mix.js.coffee
@@ -65,7 +65,6 @@
   if regionId
     wavesurfer.regions.list[regionId].remove()
     form.reset()
-  saveRegions()
   return

 window.regionsArray = ->
@@ -149,6 +148,7 @@
     return
   wavesurfer.on 'region-click', (region, e) ->
     if e.shiftKey
+      e.stopPropagation()
       region.play()
     return
   wavesurfer.on 'region-click', editAnnotation


Fix absolute url problem :owl:

Fix absolute url problem :owl:

--- app/assets/javascripts/upload.coffee
+++ app/assets/javascripts/upload.coffee
@@ -463,7 +463,7 @@
         if files.length < filez.length
           reader.readAsArrayBuffer filez[files.length]
         else
-          worker = new Worker('pdfcomprezzor/worker.js')
+          worker = new Worker('/pdfcomprezzor/worker.js')
           worker.addEventListener 'message', ((e) ->
             console.log(e.data)
             if e.data.type == 'log'
@@ -503,7 +503,7 @@
     reader.onload = () ->
       arrayBuffer = this.result
       array = new Uint8Array(arrayBuffer)
-      worker = new Worker('pdfcomprezzor/worker.js')
+      worker = new Worker('/pdfcomprezzor/worker.js')
       worker.addEventListener 'message', ((e) ->
         console.log 'Worker said: ', e
         if e.data.type == 'log'


Only search record completions by current metric

--- app/assets/volume/spreadsheet.coffee
+++ app/assets/volume/spreadsheet.coffee
@@ -769,9 +769,8 @@
                     if (r.category || 0) == info.category.id && !(ri of depends && info.i of depends[ri])
                       rs.push
                         r:r
-                        v:r.measures[info.metric.id]
+                        v:r.measures[info.metric.id].toLowerCase()
                         d:Object.keys(r.measures).sort(byNumber).map(mf(r)).join(', ')
-                        l:Object.keys(r.measures).map(mf(r)).join(' ').toLowerCase()
                   editScope.records = rs
                 else if info.metric.options
                   editScope.type = 'options'
@@ -919,7 +918,7 @@
             set = (r) -> (cell) ->
               setRecord(cell, info, r)
             for r in editScope.records
-              add("Use " + info.category.name + ' ' + r.d, set(r.r), r.v == input) if r.l.includes(inputl)
+              add("Use " + info.category.name + ' ' + r.d, set(r.r), r.v == input) if r.v.startsWith(inputl)
             v = if info.metric.options
                 (x for x in info.metric.options when x.toLowerCase().startsWith(inputl))
               else if input


add api calls

add api calls

--- app/js/controllers/dice.coffee
+++ app/js/controllers/dice.coffee
@@ -20,8 +20,20 @@
         $scope.diceSmall =$scope.diceBig = ->
             Wallet.dice(account.name, $scope.amount, $scope.payouts).then (tx)->
                 console.log(tx);
-                @wallet_api.account_transaction_history("", "", 0, Wallet.transactions_last_block, -1).then (result) =>
-                    console.log(result)
+                BlockchainAPI.get_block_count().then (blockCount) ->
+                    console.log(blockCount);
+                    startBlock = blockCount-30*24*60*60/5;
+                    if (startBlock<0)
+                        startBlock = 0
+
+                    Wallet.wallet_api.account_transaction_history("", "", 0, startBlock, -1).then (result) =>
+                        console.log(result.reverse())
+                        angular.forEach result.reverse(), (history)->
+                            Wallet.rpc.request('get_transaction', [history.trx_id]).then (response) ->
+                                tx = response.result
+                                console.log(history.trx_id)
+                                console.log(tx)
+

     $scope.enlargeBetSizeBy= (enlargeBy)->
         $scope.amount*=enlargeBy;


完了タスクを表示中は、タスク追加欄にも「完了タスクを表示中」と表示

完了タスクを表示中は、タスク追加欄にも「完了タスクを表示中」と表示

--- app/js/project/trash.js.coffee
+++ app/js/project/trash.js.coffee
@@ -28,11 +28,13 @@
         $('#tasks .task').not('#task-template').hide()
         $('.completed').show()

+        $('#task').attr('placeholder', '完了タスクを表示中')
         $('#task').attr('disabled', 'disabled')

       else
         $('#tasks .task').not('#task-template').show()
         $('.completed').hide()

+        $('#task').attr('placeholder', 'タスクを追加')
         $('#task').removeAttr('disabled')
   )


simpler event binding syntax

simpler event binding syntax

as per @eamonnerbonne 's suggestion

--- app/js/util/scrollspeed.coffee
+++ app/js/util/scrollspeed.coffee
@@ -35,7 +35,7 @@
     else
       speeding_attention.loseAttention()

-$(window).scroll check_scrolling_speed
+$(window).on 'scroll', check_scrolling_speed

 # flag to ensure we only fire on state chaneg
 currently_fast_scrolling = false


Cpp error message position (#5781)

Cpp error message position (#5781)

* convert error message offset to (row, col)

* delete testing alert

--- app/lib/aether/problems.coffee
+++ app/lib/aether/problems.coffee
@@ -170,7 +170,7 @@
       options.hint = error.message
     when 'cpp'
       if error.location
-        options.range = [error.location.start.offset, error.location.end.offset]
+        options.range = [ranges.offsetToPos(error.location.start.offset, code, codePrefix), ranges.offsetToPos(error.location.end.offset, code, codePrefix)]
       else
         console.error "C++ error with no location information:", error
       #options.hint = error.message


Added dragging into categories

Added dragging into categories

--- app/controllers/notebook.item.coffee
+++ app/controllers/notebook.item.coffee
@@ -83,15 +83,34 @@

   onDragOver: (e) =>
     e.preventDefault()
+    if @notebook.id is "all"
+      # No.
+      return false;
+    else
+      setTimeout(=>
+        @expand(e)
+      ,500)

   onDrop: (e) =>
     # Create the note in this Notebook, delete the old one. Seems like it would work.
     # Get the notebook id!
-    noteid = e.originalEvent.dataTransfer.getData('noteid')
-    note = Note.find(noteid)
-    note.updateAttributes {
-      "notebook": @notebook.id
-    }
-    Notebook.trigger('refresh')
+    if @notebook.id is "all"
+      # OMG PLS NO.
+      return false;
+    else
+      noteid = e.originalEvent.dataTransfer.getData('noteid')
+      note = Note.find(noteid)
+      if $(e.target).attr("data-category")
+        category = $(e.target).text()
+      else
+        category = "all"
+
+      note.updateAttributes {
+        "notebook": @notebook.id,
+        "category": category
+      }
+
+      # Finally, refresh!
+      Notebook.trigger('refresh')

 module.exports = NotebookItem


Copy change

Copy change

--- app/pages/lab/subject-set.cjsx
+++ app/pages/lab/subject-set.cjsx
@@ -137,7 +137,7 @@

             <input type="text" name="display_name" value={@props.subjectSet.display_name} className="standard-input full" onChange={handleInputChange.bind @props.subjectSet} />
           </AutoSave>
-          A subject set’s name is only seen by the science team.
+          A subject set’s name is only seen by the research team.

       </form>


Relax code bank section names character restrictions

--- app/schemas/models/level.ozar.coffee
+++ app/schemas/models/level.ozar.coffee
@@ -500,8 +500,8 @@
   methodsBankList: c.array {title: 'Methods Bank List'}, c.object {
     properties: {
       name: c.shortString(title: 'Name'),
-      section: c.shortString(title: 'Methods Bank Section', pattern: '^[a-z]+$'),
-      subSection: c.shortString(title: 'Methods Bank Sub-Section', pattern: '^[a-zA-Z]+$'),
+      section: c.shortString(title: 'Methods Bank Section', pattern: /^\w[\w ]*$/),
+      subSection: c.shortString(title: 'Methods Bank Sub-Section', pattern: /^\w[\w ]*$/),
       componentName: c.shortString(title: 'Level Component Name', description: 'Level Component to use for documentation in case there are multiple components with same property\'s documentation'),
     }
   }


fix highlighting issue

fix highlighting issue

--- app/scripts/filters/highlight.coffee
+++ app/scripts/filters/highlight.coffee
@@ -39,18 +39,18 @@
                 matches = [ date.toString 'yyyy' ]

         _.map matches, (match) =>
-            match = if match[0] is '0' then [(match.substr 1, match.length), match] else [match]
+            match = if match[0] is '0' then [match, match.substr 1, match.length] else [match]
             _.map match, (match) =>
                 match = do match.toLowerCase
                 i = 0
-                shift = 0
                 while i > -1
                     i = if i is 0 then lCased.indexOf match else lCased.indexOf match, i + 1
-                    if i > 0
+                    if i > 0 && str[i - 1] isnt '0'
                         tmp = str
-                        str = (tmp.substr 0, i + shift) + ""
-                        str += (tmp.substr i + shift, match.length) + ""
-                        str += tmp.substr (i + match.length + shift), tmp.length
-                        shift += 32
+                        str = (tmp.substr 0, i) + ""
+                        str += (tmp.substr i, match.length) + ""
+                        str += tmp.substr (i + match.length), tmp.length
+                        lCased = do str.toLowerCase
+                        i += 32

         str


Adding set_query_name, set_page and set_transformer

--- src/doofinder.coffee
+++ src/doofinder.coffee
@@ -81,14 +81,35 @@
     req.end()

   ###
-  add_query
+  set_query

-  This method adds a query
+  This method set query terms
   @param {String} query
   @api public
   ###
-  add_query: (term) ->
+  set_query: (term) ->
     @params.query = term
+
+
+  ###
+  set_query_name
+
+  This method set query_name
+  @param {String} query_name
+  @api public
+  ###
+  set_query_name: (query_name) ->
+    @params.query_name = query_name
+
+  ###
+  set_query_name
+
+  This method set page
+  @param {int} page
+  @api public
+  ###
+  set_page: (term) ->
+    @params.page = page

   ###
   add_filter
@@ -133,8 +154,9 @@
   ###
   make_querystring

-  This method prepare returns a
-  querystring for request
+  This method returns a
+  querystring for adding
+  to Search API request.

   @returns {String} querystring
   @api private


updated methods

updated methods

--- src/drm-modal.coffee
+++ src/drm-modal.coffee
@@ -3,24 +3,25 @@
 ###############################################################################
 "use strict"

+$ = jQuery
 class @DrmModal
     constructor: (@buttons = $('button.drm-modal-open'), @lightbox = $('div.drm-modal-lightbox'), @speed = 300) ->
         self = @
-        modals = self.lightbox.find 'div.drm-modal'
-        close = modals.find 'button.drm-modal-close'
+        _modals = self.lightbox.find 'div.drm-modal'
+        _close = _modals.find 'button.drm-modal-close'

         self.buttons.on 'click', -> self.showModal.call @, self.speed

-        close.on 'click', $.proxy self.hideModal, self
+        _close.on 'click', $.proxy self.hideModal, self

         self.lightbox.on 'click', $.proxy self.hideModal, self

-        modals.on 'click', (e) ->
+        _modals.on 'click', (e) ->
             e.stopPropagation()

     showModal: (speed) ->
-        modalId = $(@).data 'modal'
-        $("##{modalId}").fadeIn speed
+        _modalId = $(@).data 'modal'
+        $("##{_modalId}").fadeIn speed

     hideModal: (e) ->
         @lightbox.fadeOut @speed


filter is maybe more precise instead of first

--- src/dt-jquery.coffee
+++ src/dt-jquery.coffee
@@ -96,14 +96,14 @@
                 if $par.parent().length > 0
                     if parent._jquery_wrapped is yes
                         parent._jquery_wrapped = no
-                        $par.first().replaceWith(el._jquery)
+                        $par.filter('spaceholder').replaceWith(el._jquery)
                     else
                         el._jquery.insertAfter($par[i])
             else
                 $par.append(el._jquery)
             if parent._jquery_wrapped is yes
                 parent._jquery_wrapped = no
-                $par.first().remove() # rm placeholder span
+                $par.filter('spaceholder').remove() # rm placeholder span

         replace: (oldtag, newtag) =>
             return if removed newag


$.after doesnt work with $([…])

$.after doesnt work with $([…])

--- src/dt-jquery.coffee
+++ src/dt-jquery.coffee
@@ -98,7 +98,7 @@
                         parent._jquery_wrapped = no
                         $par.first().replaceWith(el._jquery)
                     else
-                        el._jquery.after($par[i])
+                        el._jquery.insertAfter($par[i])
             else
                 $par.append(el._jquery)
             if parent._jquery_wrapped is yes


sets up follow button

sets up follow button

--- apps/artist_new/client/router.coffee
+++ apps/artist_new/client/router.coffee
@@ -12,6 +12,7 @@
 CollectionsView = require './views/collections.coffee'
 mediator = require '../../../lib/mediator.coffee'
 splitTest = require '../../../components/split_test/index.coffee'
+{ Following, FollowButton } = require '../../../components/follow_button/index.coffee'
 attachCTA = require './cta.coffee'

 module.exports = class ArtistRouter extends Backbone.Router
@@ -28,9 +29,21 @@
     @options = model: @model, user: @user

     @setupUser()
+    @setupFollowButton()

   setupUser: ->
     @user?.initializeDefaultArtworkCollection()
+
+  setupFollowButton: ->
+    @following = new Following(null, kind: 'artist') if @user
+    new FollowButton
+      analyticsFollowMessage: 'Followed artist, via artist header'
+      analyticsUnfollowMessage: 'Unfollowed artist, via artist header'
+      el: $('#artist-follow-button')
+      following: @following
+      modelName: 'artist'
+      model: @model
+    @following?.syncFollows [@model.id]

   execute: ->
     return if @view? # Sets up a view once, depending on route


Switch to making gain available for mute/unmute

--- player.coffee
+++ player.coffee
@@ -37,7 +37,12 @@

     @av_info = @core.get_system_av_info()

-    # audio
+    @initAudio()
+
+    @core.load_game @game if @game?
+    @core.unserialize @save if @save?
+
+  initAudio: ->
     @then = 0
     @sampleRate = @av_info.timing.sample_rate
     @numBuffers = Math.floor @latency * @sampleRate / (1000 * @bufferSize)
@@ -50,9 +55,9 @@
       i++
     @bufOffset = 0
     @bufIndex = 0
-
-    @core.load_game @game if @game?
-    @core.unserialize @save if @save?
+    @destination = @audio.createGain()
+    @destination.gain.value = 1
+    @destination.connect @audio.destination

   initGL: ->
     fragmentShader = @gl.createShader @gl.FRAGMENT_SHADER
@@ -200,7 +205,7 @@
         @buffers[@bufIndex].endTime = startTime + @buffers[@bufIndex].duration
         source = @audio.createBufferSource()
         source.buffer = @buffers[@bufIndex]
-        source.connect @audio.destination
+        source.connect @destination
         source.start startTime
         @bufIndex++
         @bufOffset = 0


use logger instead of console

use logger instead of console

--- plugin.coffee
+++ plugin.coffee
@@ -4,9 +4,9 @@
 path = require 'path'
 postcss = require 'postcss'

-module.exports = (env, callback) ->
+module.exports = (wintersmith, callback) ->

-  class PostCSSPlugin extends env.ContentPlugin
+  class PostCSSPlugin extends wintersmith.ContentPlugin

     constructor: (@_filepath, @_text) ->

@@ -26,7 +26,7 @@
           postcss(plugins)
             .process(@_text, options)
             .then (result) -> callback null, new Buffer(result.css)
-            .catch (error) -> console.error error
+            .catch (error) -> wintersmith.logger.error error.toString()

         catch error
           callback error
@@ -38,5 +38,5 @@
         return
       callback null, new PostCSSPlugin(filepath, buffer.toString())

-  env.registerContentPlugin 'styles', '**/*.css', PostCSSPlugin
+  wintersmith.registerContentPlugin 'styles', '**/*.css', PostCSSPlugin
   callback()


#0 @xq 修正变量

#0 @xq 修正变量

--- honey/index.coffee
+++ honey/index.coffee
@@ -53,46 +53,72 @@
   $('body').append html
   $.html()

+#获取环境变量
+getVariables = (env, server, project_name)->
+  previewServer = "http://#{server}.preview.lab.hunantv.com/#{project_name}/"
+  cssHunantv = "http://css.hunantv.com/#{project_name}/"
+  imgHunantv = "http://img.hunantv.com/#{project_name}/"
+  jsHunantv = "http://js.hunantv.com/#{project_name}/"
+  imgDemo = "http://image-demo.lab.hunantv.com/#{project_name}/"
+  pubTemplate = "/imgotv-pub/template/"
+  compDir = "imgotv-pub/component/"
+
+  data =
+    preview:
+      __css: "#{previewServer}css/"
+      __js: "#{previewServer}js/"
+      __img: "#{previewServer}image/"
+      __pub_img: "#{previewServer}image/imgotv-pub/"
+      __img_demo: imgDemo
+      __pub_font: "#{previewServer}/font/"
+      __base_url: "/#{project_name}/"
+      __pub_css_comp: "#{previewServer}css/#{compDir}"
+    development:
+      __css: "/css/"
+      __js: "/js/"
+      __img: "/image/"
+      __pub_img: "/imgotv-pub/image/"
+      __img_demo: "/image-demo/"
+      __pub_font: "/font/"
+      __base_url: "/"
+      __pub_css_comp: "/imgotv-pub/css/component/"
+    production:
+      __pub_font: "#{cssHunantv}/font/"
+      __css: cssHunantv
+      __js: jsHunantv
+      __img: imgHunantv
+      __img_demo: imgDemo
+      __pub_img: "#{imgHunantv}imgotv-demo/"
+      __base_url: "/#{project_name}/"
+      __pub_css_comp: "#{cssHunantv}#{compDir}"
+
+  variables = data[env]
+
+  _.extend variables,
+    __standard_css: "http://css.hunantv.com/standard/"
+    __pub_tmpl: pubTemplate
+    __project: project_name
+    __pub_tmpl_comp: "#{pubTemplate}component/"
+    __pub_tmpl_ui: "#{pubTemplate}ui/"
+    __pub_tmpl_widget: "#{pubTemplate}widget/"
+
+  variables
+
+#更改config的配置
+changeConfig = (silky)->
+  #添加路由配置
+#  routers = silky.config.routers
+#  buildRename = silky.config.rename
+#  buildRename.push
+#    {
+#      source: /^imgotv\-pub[\/|\\]\/(.+)/i, target: '/$1', next: false
+#    }
+
 #添加系统变量
 appendSystemVariable = (silky)->
-  isProduction = silky.utils.isProduction
   project_name = silky.config.name || _path.basename silky.options.workbench

-  cssProduction = "http://css.hunantv.com/#{project_name}/"
-  jsProduction = "http://js.hunantv.com/#{project_name}/"
-  imgProduction = "http://img.hunantv.com/#{project_name}/"
-  pubImgProduction = "#{imgProduction}imgotv-pub/"
-  pubFontProduction = "#{cssProduction}imgotv-pub/font/"
-  pubCssProduction = "http://css.hunantv.com/imgotv-pub/"
-  pubCssCompProduction = "http://css.hunantv.com/standard/"
-
-  pubTemplate = "/imgotv-pub/template/"
-  variables =
-    #公共的css路径
-    __pub_css: if isProduction then pubCssProduction else "/imgotv-pub/css/"
-    #css的位置
-    __css: if isProduction then cssProduction else "/css/"
-    #js路径
-    __js: if isProduction then jsProduction else "/js/"
-    #图片路径
-    __img: if isProduction then imgProduction else "/image/"
-    #公共模板
-    __pub_tmpl: pubTemplate
-    #项目名称
-    __project: project_name
-    #公共库的图片
-    __pub_img: if isProduction then pubImgProduction else "/imgotv-pub/image/"
-    #公共库的字体
-    __pub_font: if isProduction then pubFontProduction else "/font/"
-    #公共模板
-    __pub_tmpl_comp: "#{pubTemplate}component/"
-    #__pub_tmpl_module: "#{pubTemplate}module"
-    __pub_tmpl_ui: "#{pubTemplate}ui"
-    __pub_tmpl_widget: "#{pubTemplate}widget/"
-    #全局组件的css
-    __pub_css_comp: if isProduction then pubCssCompProduction else "/imgotv-pub/css/component/"
-    #demo图片的地址
-    __img_demo: if isProduction then "http://image-demo.lab.hunantv.com/#{project_name}/" else "/image-demo/"
+  variables = getVariables silky.options.env, 108, project_name

   #把变量加到global中去
   jsonData = silky.data.json
@@ -100,7 +126,7 @@
   _.defaults jsonData.global, variables

   #把变量加到less中
-  pubLess = "../imgotv-pub/css/";
+  pubLess = "/imgotv-pub/css/";
   pubIncludeLess = "#{pubLess}include/";
   lessData = silky.data.less
   lessData.global = lessData.global || ''
@@ -123,7 +149,12 @@
 exports.registerPlugin = (silky, pluginOptions)->
   #在build和路由启动的时候，加入系统变量
   silky.registerHook 'route:initial', -> appendSystemVariable silky
-  silky.registerHook 'build:initial', -> appendSystemVariable silky
+  silky.registerHook 'build:initial', ->
+    #build时没有指定环境，则假定为preview环境
+    #如果没有指定环境，则指定为preview环境，以解决上传到预览服务器的路径问题
+    #在正式编译的时候，环境会被设置为production环境
+    silky.options.env = 'preview' if not silky.options.original.env
+    appendSystemVariable silky

   silky.registerHook 'route:willResponse', {}, (data, done)->
     url = _url.parse data.request.url


Simplify exclusions.coffee

Simplify exclusions.coffee

--- background_scripts/exclusions.coffee
+++ background_scripts/exclusions.coffee
@@ -5,13 +5,15 @@
     if pattern of @cache
       @cache[pattern]
     else
-      @cache[pattern] =
-        # We use try/catch to ensure that a broken regexp doesn't wholly cripple Vimium.
-        try
-          new RegExp("^" + pattern.replace(/\*/g, ".*") + "$")
-        catch
-          BgUtils.log "bad regexp in exclusion rule: #{pattern}"
-          /^$/ # Match the empty string.
+      result = null
+      # We use try/catch to ensure that a broken regexp doesn't wholly cripple Vimium.
+      try
+        result = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$")
+      catch
+        BgUtils.log "bad regexp in exclusion rule: #{pattern}"
+        result = /^$/ # Match the empty string.
+      @cache[pattern] = result
+      return result

 # The Exclusions class manages the exclusion rule setting.  An exclusion is an object with two attributes:
 # pattern and passKeys.  The exclusion rules are an array of such objects.
@@ -25,33 +27,37 @@
   # Merge the matching rules for URL, or null.  In the normal case, we use the configured @rules; hence, this
   # is the default.  However, when called from the page popup, we are testing what effect candidate new rules
   # would have on the current tab.  In this case, the candidate rules are provided by the caller.
-  getRule: (url, rules = @rules) ->
-    matchingRules = (rule for rule in rules when rule.pattern and 0 <= url.search RegexpCache.get rule.pattern)
+  getRule: (url, rules) ->
+    if !rules
+      rules = @rules
+    matchingRules = rules.filter((r) => r.pattern and url.search(RegexpCache.get(r.pattern)) >= 0)
     # An absolute exclusion rule (one with no passKeys) takes priority.
     for rule in matchingRules
       return rule unless rule.passKeys
     # Strip whitespace from all matching passKeys strings, and join them together.
-    passKeys = (rule.passKeys.split(/\s+/).join "" for rule in matchingRules).join ""
-    if 0 < matchingRules.length
+    passKeys = matchingRules.map((r) => r.passKeys.split(/\s+/).join("")).join("")
+    if matchingRules.length > 0
       passKeys: Utils.distinctCharacters passKeys
     else
       null

   isEnabledForUrl: (url) ->
     rule = Exclusions.getRule url
-    isEnabledForUrl: not rule or 0 < rule.passKeys.length
-    passKeys: rule?.passKeys ? ""
+    isEnabledForUrl: not rule or rule.passKeys.length > 0
+    passKeys: if rule then rule.passKeys else ""

   setRules: (rules) ->
     # Callers map a rule to null to have it deleted, and rules without a pattern are useless.
-    @rules = rules.filter (rule) -> rule and rule.pattern
+    @rules = rules.filter((rule) -> rule and rule.pattern)
     Settings.set "exclusionRules", @rules
+    return

   postUpdateHook: (rules) ->
     # NOTE(mrmr1993): In FF, the |rules| argument will be garbage collected when the exclusions popup is
     # closed. Do NOT store it/use it asynchronously.
     @rules = Settings.get "exclusionRules"
     RegexpCache.clear()
+    return

 # Register postUpdateHook for exclusionRules setting.
 Settings.postUpdateHooks["exclusionRules"] = Exclusions.postUpdateHook.bind Exclusions


Update hubot-cah.coffee

Update hubot-cah.coffee

--- src/hubot-cah.coffee
+++ src/hubot-cah.coffee
@@ -294,7 +294,6 @@
             msg.reply "You cannot submit a single card more than once."
             return
       submit_answer(sender(msg), nums)
-      robot.brain.save()
       msg.reply "Submission accepted."

   robot.hear /^cah answers$/i, (msg) ->
@@ -319,11 +318,9 @@
         msg.reply "That is not an valid choice, try again."
       else
         msg.send czar_choose_winner num
-        robot.brain.save()

   robot.hear /^cah (status|question)$/i, (msg) ->
     msg.send game_state_string()

   robot.hear /^cah skip$/i, (msg) ->
     msg.send czar_choose_winner -1
-    robot.brain.save()


Very initial browser loadJSON

Very initial browser loadJSON

--- src/lib/Graph.coffee
+++ src/lib/Graph.coffee
@@ -319,16 +319,24 @@

   success graph

-exports.loadFile = (file, success) ->
-  fs.readFile file, "utf-8", (err, data) ->
-    throw err if err
-
-    if file.split('.').pop() is 'fbp'
-      return exports.loadFBP data, success
-
-    definition = JSON.parse data
-    exports.loadJSON definition, success
-
 exports.loadFBP = (fbpData, success) ->
   definition = fbp.parse fbpData
   exports.loadJSON definition, success
+
+exports.loadFile = (file, success) ->
+  unless typeof process is 'object' and process.title is 'node'
+    try
+      definition = require file
+      exports.loadJSON definition, success
+    catch e
+      # TODO: Try AJAX GET
+      throw new Error "Failed to load graph #{file}"
+    return
+  fs.readFile file, "utf-8", (err, data) ->
+    throw err if err
+
+    if file.split('.').pop() is 'fbp'
+      return exports.loadFBP data, success
+
+    definition = JSON.parse data
+    exports.loadJSON definition, success


a simple implementation of commands to create criticmarkup tags

i think it is more like a draft of a possible implementation

--- spec/commands/style-text-spec.coffee
+++ spec/commands/style-text-spec.coffee
@@ -29,7 +29,7 @@
       expect(cmd.isStyleOn(fixture)).toBe(true)

     it "check any addition is in string", ->
-      cmd = new StyleTehttps://github.com/zhuochun/md-writer/issues/221xt("addition")
+      cmd = new StyleText("addition")
       fixture = "**bold** one {++addition++} two _italic_"
       expect(cmd.isStyleOn(fixture)).toBe(true)


More accurate --vaults spec name

More accurate --vaults spec name

--- spec/integrations/vaults.spec.coffee
+++ spec/integrations/vaults.spec.coffee
@@ -10,7 +10,7 @@
         Marker: 'test'
         VaultList: [ VaultName: 'Bird' ]

-  it 'should honor the iced_host and iced_port environment variables', (done) ->
+  it 'should list vaults in an amazon glacier account', (done) ->
     out = command '--vaults', (err, stdout, stderr) ->
       expect(err).to.be.falsy
       expect(stderr).to.be.falsy


No need to test visibility of main

No need to test visibility of main

--- spec/javascripts/tahi_spec.js.coffee
+++ spec/javascripts/tahi_spec.js.coffee
@@ -79,7 +79,6 @@
     it "shows the overlay div", ->
       Tahi.displayOverlay($('#planes'))
       expect($('#overlay')).toBeVisible()
-      expect($('#overlay main')).toBeVisible()

     describe "when the overlay is dismissed", ->
       it "moves back the overlay content to its original container", ->


Remove useless config

Remove useless config

--- views/components/settings/parts/plugin-config.cjsx
+++ views/components/settings/parts/plugin-config.cjsx
@@ -85,7 +85,6 @@
       updating = @state.updating
       updating[index] = true
       npm.load {prefix: "#{PLUGIN_PATH}"}, (err) ->
-        npm.config.set '-global-style', true
         npm.commands.update [plugins[index].packageName], (er, data) ->
           callback(index)
       @setState {updating}