bug fix: modal hiding when introspect wasn't properly focusing cursor back on editor on close

--- salvus/page/misc_page.coffee
+++ salvus/page/misc_page.coffee
@@ -451,13 +451,12 @@
             content   : required
             type      : required   # 'docstring', 'source-code' -- TODO
             target    : required
-        editor = @
         element = templates.find(".salvus-codemirror-introspect")
         element.find(".salvus-codemirror-introspect-title").text(opts.target)
         element.modal()
         element.find(".salvus-codemirror-introspect-content-docstring").text('')
         element.find(".salvus-codemirror-introspect-content-source-code").text('')
-        element.data('editor',editor)
+        element.data('editor', @)
         if opts.type == 'source-code'
             CodeMirror.runMode(opts.content, 'python', element.find(".salvus-codemirror-introspect-content-source-code")[0])
         else
@@ -539,11 +538,15 @@
         end_line = start_line
     return {start_line:start_line, end_line:end_line}

-
-templates.find(".salvus-codemirror-introspect").find("button").click () ->
-    templates.find(".salvus-codemirror-introspect").modal('hide')
-    element.data('editor').focus()
-    element.data('editor',0)
+codemirror_introspect_modal = templates.find(".salvus-codemirror-introspect")
+
+codemirror_introspect_modal.find("button").click () ->
+    codemirror_introspect_modal.modal('hide')
+
+# see http://stackoverflow.com/questions/8363802/bind-a-function-to-twitter-bootstrap-modal-close
+codemirror_introspect_modal.on 'hidden.bs.modal', () ->
+    codemirror_introspect_modal.data('editor').focus?()
+    codemirror_introspect_modal.data('editor',0)

 exports.download_file = (url) ->
     iframe = $("<iframe>").addClass('hide').attr('src', url).appendTo($("body"))
@@ -588,13 +591,6 @@
 ###

-
-
-
-
-
-
-
 marked = require('marked')

 marked.setOptions
@@ -643,7 +639,6 @@
     else
         return not isNaN(d.getTime())

-
 # Bootstrap 3 modal fix
 $("html").on "hide.bs.modal", "body > .modal", (e) ->
     $(@).remove()
@@ -659,9 +654,6 @@
 # Use this because CSS and JS display different widths due to scrollbar
 exports.is_responsive_mode = () ->
     return $(".salvus-responsive-mode-test").width() < 768
-
-
-

 exports.load_coffeescript_compiler = (cb) ->
     if CoffeeScript?
@@ -671,7 +663,6 @@
         $.getScript "/static/coffeescript/coffee-script.js", (script, status) ->
             console.log("loaded CoffeeScript -- #{status}")
             cb()
-

 # Convert html to text safely using jQuery (see http://api.jquery.com/jquery.parsehtml/)


Show label editor on new control added, fix #909

--- src/resources/forms/orbeon/builder/resources/cell/label-hint-editor.coffee
+++ src/resources/forms/orbeon/builder/resources/cell/label-hint-editor.coffee
@@ -1,7 +1,9 @@
 $ ->
+    Builder = ORBEON.Builder
     OD = ORBEON.xforms.Document

     LabelHintSelector = '.fr-editable .xforms-label, .fr-editable .xforms-hint'
+    ControlSelector = '.xforms-control, .xbl-component'

     # Global state
     currentControl = null
@@ -65,18 +67,7 @@
         editor

     # Show editor on click on label
-    startEdit = ({currentTarget}) ->
-        currentLabelHint = $(currentTarget)
-        # Find control for this label
-        th = currentLabelHint.parents('th')
-        currentControl =
-            if th.is('*')
-                # Case of a repeat
-                trWithControls = th.parents('table').find('tbody tr.fb-grid-tr').first()
-                tdWithControl = trWithControls.children(':nth-child(' + (th.index() + 1) + ')')
-                tdWithControl.find('.xforms-control, .xbl-component')
-            else
-                currentLabelHint.parents('.xforms-control, .xbl-component').first()
+    startEdit = () ->
         # Remove `for` so browser doesn't set the focus to the control on click
         currentLabelHint.removeAttr('for')
         # Setup tooltip for editor (don't do this once for all, as the language can change)
@@ -90,5 +81,28 @@
         labelHintEditor().textfield.val(labelHintValue()).focus()
         labelHintEditor().checkbox.prop('checked', isLabelHintHtml())

-    $('.fb-main').on('click', LabelHintSelector, startEdit)
+    # Click on label/hint
+    $('.fb-main').on 'click', LabelHintSelector, ({currentTarget}) ->
+        currentLabelHint = $(currentTarget)
+        # Find control for this label
+        th = currentLabelHint.parents('th')
+        currentControl =
+            if th.is('*')
+                # Case of a repeat
+                trWithControls = th.parents('table').find('tbody tr.fb-grid-tr').first()
+                tdWithControl = trWithControls.children(':nth-child(' + (th.index() + 1) + ')')
+                tdWithControl.find(ControlSelector)
+            else
+                currentLabelHint.parents(ControlSelector).first()
+        startEdit()

+    # New control added
+    Builder.controlAdded.add (containerId) ->
+        container = $(document.getElementById(containerId))
+        currentControl = container.find(ControlSelector)
+        repeat = container.parents('.fr-repeat').first()
+        currentLabelHint =
+            if   repeat.is('*') \
+            then repeat.find('thead tr th:nth-child(' + (container.index() + 1) + ') .xforms-label')
+            else container.find('.xforms-label')
+        startEdit()


continue migration even if there's an exception while migrating any crypto service

--- js/src/crypto/CryptoServiceMigrator.coffee
+++ js/src/crypto/CryptoServiceMigrator.coffee
@@ -103,22 +103,29 @@

           logger.info('attempting to migrate RSA crypto service for objectId: ' + objectId)

-          rsaEncryptedMarshalledCryptoService = atob(serializedCryptoService)
-          marshalledCryptoService = @rsaCryptoService.decrypt(rsaEncryptedMarshalledCryptoService)
-          objectCryptoService = @cryptoServiceMarshaller.unmarshall(marshalledCryptoService)
+          try

-          marshalledCryptoService = @cryptoServiceMarshaller.marshall(objectCryptoService)
-          encryptedCryptoService  = masterAesCryptoService.encrypt(marshalledCryptoService)
+            rsaEncryptedMarshalledCryptoService = atob(serializedCryptoService)
+            marshalledCryptoService = @rsaCryptoService.decrypt(rsaEncryptedMarshalledCryptoService)
+            objectCryptoService = @cryptoServiceMarshaller.unmarshall(marshalledCryptoService)

-          Promise.resolve(
-            setAesEncryptedObjectCryptoServiceForMigration(objectId, encryptedCryptoService)
-          )
-          .then ->
-            logger.info('successfully migrated RSA crypto service for objectId: ' + objectId)
-            return
-          .catch (e) ->
-            logger.info('failed to migrate RSA crypto service for objectId: ' + objectId)
-            return
+            marshalledCryptoService = @cryptoServiceMarshaller.marshall(objectCryptoService)
+            encryptedCryptoService  = masterAesCryptoService.encrypt(marshalledCryptoService)
+
+            Promise.resolve(
+              setAesEncryptedObjectCryptoServiceForMigration(objectId, encryptedCryptoService)
+            )
+            .then ->
+              logger.info('successfully migrated RSA crypto service for objectId: ' + objectId)
+              return
+            .catch (e) ->
+              logger.info('failed to migrate RSA crypto service for objectId: ' + objectId)
+              return
+
+          catch e
+            logger.error(e)
+            logger.error('error while migrating RSA crypto service for objectId: ' + objectId)
+            return Promise.resolve()
         )

         Promise.all(migrationPromises)


Dispose packages subscriptions

Dispose packages subscriptions

See #537

--- lib/package-card.coffee
+++ lib/package-card.coffee
@@ -1,5 +1,6 @@
 _ = require 'underscore-plus'
 {View} = require 'atom-space-pen-views'
+{CompositeDisposable} = require 'atom'
 shell = require 'shell'
 marked = null
 {ownerFromRepository} = require './utils'
@@ -52,6 +53,8 @@
               @button type: 'button', class: 'btn status-indicator', tabindex: -1, outlet: 'statusIndicator'

   initialize: (@pack, @packageManager, options) ->
+    @disposables = new CompositeDisposable()
+
     # It might be useful to either wrap @pack in a class that has a ::validate
     # method, or add a method here. At the moment I think all cases of malformed
     # package metadata are handled here and in ::content but belt and suspenders,
@@ -166,7 +169,7 @@
       false

   detached: ->
-    @packageManagerSubscription.dispose()
+    @disposables.dispose()

   loadCachedMetadata: ->
     @client.avatar ownerFromRepository(@pack.repository), (err, avatarPath) =>
@@ -318,13 +321,13 @@
         'This package has deprecations and is not installable.'

   handlePackageEvents: ->
-    atom.packages.onDidDeactivatePackage (pack) =>
+    @disposables.add atom.packages.onDidDeactivatePackage (pack) =>
       @updateDisabledState() if pack.name is @pack.name

-    atom.packages.onDidActivatePackage (pack) =>
+    @disposables.add atom.packages.onDidActivatePackage (pack) =>
       @updateDisabledState() if pack.name is @pack.name

-    atom.config.onDidChange 'core.disabledPackages', =>
+    @disposables.add atom.config.onDidChange 'core.disabledPackages', =>
       @updateDisabledState()

     @subscribeToPackageEvent 'package-installing', (pack) =>
@@ -382,7 +385,7 @@
     false

   subscribeToPackageEvent: (event, callback) ->
-    @packageManagerSubscription = @packageManager.on event, (pack, error) =>
+    @disposables.add @packageManager.on event, (pack, error) =>
       packageName = pack.name
       packageName = pack.pack.name if pack.pack?
       callback(pack, error) if packageName is @pack.name


Don't reload paths on focus until task completes

Let the initial task complete but mark the reload as being
needed once it completes so a fresh reload is still performed
but the first set of paths is presented instead of just showing
the loading indicator again.

Closes #23

--- lib/project-view.coffee
+++ lib/project-view.coffee
@@ -8,6 +8,7 @@
 class ProjectView extends FuzzyFinderView
   paths: null
   reloadPaths: true
+  reloadAfterFirstLoad: false

   initialize: (@paths) ->
     super
@@ -15,7 +16,13 @@
     @reloadPaths = false if @paths?.length > 0

     @subscribe $(window), 'focus', =>
-      @reloadPaths = true
+      if @paths?
+        @reloadPaths = true
+      else
+        # The window gained focused while the first task was still running
+        # so let it complete but reload the paths on the next populate call.
+        @reloadAfterFirstLoad = true
+
     @subscribe atom.config.observe 'fuzzy-finder.ignoredNames', callNow: false, =>
       @reloadPaths = true

@@ -39,7 +46,12 @@
     if @reloadPaths
       @reloadPaths = false
       @loadPathsTask?.terminate()
-      @loadPathsTask = PathLoader.startTask (@paths) => @populate()
+      @loadPathsTask = PathLoader.startTask (@paths) =>
+        if @reloadAfterFirstLoad
+          @reloadPaths = true
+          @reloadAfterFirstLoad = false
+
+        @populate()

       if @paths?
         @setLoading("Reindexing project\u2026")


Improve #sortableRangeForEntireBuffer

Improve #sortableRangeForEntireBuffer

We shouldn't use #getScreenLineCount here. It takes into account folded
lines, which will not be the entire buffer range if anything in it is
currently folded. Instead, we can simplify this method by using a method
that's already baked into Atom. :boom:

Thanks, @kevinsawicki!

--- lib/range-finder.coffee
+++ lib/range-finder.coffee
@@ -26,10 +26,7 @@

   # Internal
   sortableRangeForEntireBuffer: ->
-    endRow = @editor.getScreenLineCount()
-    endCol = @editor.lineLengthForBufferRow(endRow)
-
-    new Range [0, 0], [endRow, endCol]
+    @editor.getBuffer().getRange()

   # Internal
   sortableRangeFrom: (selectionRange) ->


add instructions

add instructions

--- test-integration/simple.coffee
+++ test-integration/simple.coffee
@@ -1,3 +1,15 @@
+# Runs some selenium tests that create an iReading (saves screenshot on failure). Mostly just playing around with Selenium to get feedback. The actual test code is in `simple.coffee`
+#
+# # Instructions
+#
+# 1. `npm install -g mocha`
+# 2. `npm install` (to get the new packages)
+# 3. `mocha ./test-integration/simple.coffee --compilers coffee-script/register`
+#
+# TODO:
+#
+# - [ ] Abstract reading creation so it can be used for "Save Draft", "Publish" and partial completion
+
 {describe} = require './helper'
 selenium = require 'selenium-webdriver'
 {expect} = require 'chai'


Handle missing stylus node in style compilation

--- lib/styles/index.coffee
+++ lib/styles/index.coffee
@@ -34,3 +34,6 @@

             callback?()

+    else
+      console.log 'stylus node not included in package - skipping style compilation'
+      callback?()


s/target/currentTarget/

s/target/currentTarget/

--- lib/upi-consumer.coffee
+++ lib/upi-consumer.coffee
@@ -97,27 +97,27 @@
         if t = atom.config.get('haskell-ghc-mod.onSelectionShow')
           @["#{t}Tooltip"] editor, crange

-  checkCommand: ({target}) =>
-    editor = target.getModel()
+  checkCommand: ({currentTarget}) =>
+    editor = currentTarget.getModel()
     @process.doCheckBuffer(editor.getBuffer()).then (res) =>
       @setMessages res, ['error', 'warning']

-  lintCommand: ({target}) =>
-    editor = target.getModel()
+  lintCommand: ({currentTarget}) =>
+    editor = currentTarget.getModel()
     @process.doLintBuffer(editor.getBuffer()).then (res) =>
       @setMessages res, ['lint']

   tooltipCommand: (tooltipfun) =>
-    ({target, detail}) =>
+    ({currentTarget, detail}) =>
       @upi.showTooltip
-        editor: target.getModel()
+        editor: currentTarget.getModel()
         detail: detail
         tooltip: (crange) ->
-          tooltipfun target.getModel(), crange
-
-  insertTypeCommand: ({target, detail}) =>
+          tooltipfun currentTarget.getModel(), crange
+
+  insertTypeCommand: ({currentTarget, detail}) =>
     Util = require './util'
-    editor = target.getModel()
+    editor = currentTarget.getModel()
     @upi.withEventRange {editor, detail}, ({crange, pos}) =>
       @process.getTypeInBuffer(editor.getBuffer(), crange)
       .then (o) ->
@@ -138,16 +138,16 @@
           editor.setTextInBufferRange o.range,
             "(#{editor.getTextInBufferRange(o.range)} :: #{type})"

-  caseSplitCommand: ({target, detail}) =>
-    editor = target.getModel()
+  caseSplitCommand: ({currentTarget, detail}) =>
+    editor = currentTarget.getModel()
     @upi.withEventRange {editor, detail}, ({crange}) =>
       @process.doCaseSplit(editor.getBuffer(), crange)
       .then (res) ->
         res.forEach ({range, replacement}) ->
           editor.setTextInBufferRange(range, replacement)

-  sigFillCommand: ({target, detail}) =>
-    editor = target.getModel()
+  sigFillCommand: ({currentTarget, detail}) =>
+    editor = currentTarget.getModel()
     @upi.withEventRange {editor, detail}, ({crange}) =>
       @process.doSigFill(editor.getBuffer(), crange)
       .then (res) ->
@@ -165,8 +165,8 @@
             for row in newrange.getRows().slice(1)
               editor.setIndentationForBufferRow row, indent

-  goToDeclCommand: ({target, detail}) =>
-    editor = target.getModel()
+  goToDeclCommand: ({currentTarget, detail}) =>
+    editor = currentTarget.getModel()
     @upi.withEventRange {editor, detail}, ({crange}) =>
       @process.getInfoInBuffer(editor, crange)
       .then ({range, info}) =>
@@ -178,8 +178,8 @@
           initialLine: parseInt(line) - 1
           initialColumn: parseInt(col) - 1

-  insertImportCommand: ({target, detail}) =>
-    editor = target.getModel()
+  insertImportCommand: ({currentTarget, detail}) =>
+    editor = currentTarget.getModel()
     buffer = editor.getBuffer()
     @upi.withEventRange {editor, detail}, ({crange}) =>
       @process.findSymbolProvidersInBuffer editor, crange


simplified querying, removed unneeded comma

--- core/app/backbone/views/activities_view.coffee
+++ core/app/backbone/views/activities_view.coffee
@@ -54,7 +54,7 @@
   emptyViewOn: ->
     @suggestedTopics = new SuggestedTopics([], user: @collection.channel.user())
     @emptyView = new emptyActivitiesView
-      el: @$el.find('.empty_stream'),
+      el: @$('.empty_stream')
       collection: @suggestedTopics

     @emptyView.render()


fix checkbox binding

fix checkbox binding

--- lib/client/javascripts/nali/view.js.coffee
+++ lib/client/javascripts/nali/view.js.coffee
@@ -229,7 +229,7 @@
       _node = @_ node

       updateSource = ->
-        ( params = {} )[ property ] = node.value
+        ( params = {} )[ property ] = if node.type is 'checkbox' and !node.checked then null else node.value
         source.update params
         source.save() unless node.form?

@@ -242,7 +242,7 @@
         when node.type in [ 'checkbox', 'radio' ]
           [
             -> node.checked = source[ property ] + '' is node.value
-            -> _node.on 'change', => updateSource.call @ if node.checked is true
+            -> _node.on 'change', => updateSource.call @ if node.type is 'checkbox' or node.checked is true
           ]
         when node.type is 'select-one'
           [


Added isActive function to workspace manager

--- lib/common/levels-workspace-manager.coffee
+++ lib/common/levels-workspace-manager.coffee
@@ -40,6 +40,10 @@
     isDebuggable = @getActiveLevel()?.getOption 'debuggable'
     return isDebuggable? && isDebuggable

+  isActive: ->
+    isActive = @levelsWorkspace?.isActive()
+    return isActive? && isActive
+
   getActiveTextEditorCursorPositions: ->
     return @getActiveTextEditor()?.getCursorBufferPositions()


delete node: avoid child node delete

delete node: avoid child node delete

--- src/app/view/tree/TreeController.coffee
+++ src/app/view/tree/TreeController.coffee
@@ -113,9 +113,10 @@
             buttons: Ext.MessageBox.YESNO
             fn: (btn) ->
                 if btn is "yes"
-                    #store = record.getTreeStore()
+                    # avoid delete requests for contained childnodes,
+                    # since these contained items are deleted by Plone anyway
+                    record.childNodes = []
                     record.remove()
-                    #store.reload()

             icon: Ext.MessageBox.QUESTION
             scope: @


Check all states

Check all states

--- client/landing/app/Applications/Account.kdapplication/account/accSettingsPersEmailNotifications.coffee
+++ client/landing/app/Applications/Account.kdapplication/account/accSettingsPersEmailNotifications.coffee
@@ -68,7 +68,7 @@

     toggleFieldStates = (state)->
       for flag, field of fields when flag isnt 'global'
-        if state is 'off'
+        if state in ['off', 'never']
           field.formView.hide()
         else
           field.formView.show()


Shorten variable name

Shorten variable name

--- skeletons/skeleton.coffee
+++ skeletons/skeleton.coffee
@@ -4,4 +4,4 @@
 Template.BASENAME.rendered = ->

 Template.BASENAME.events
-#  "click .selector": (e, template) ->
+#  "click .selector": (e, t) ->


Update ru/welcome.cson (#244)

Update ru/welcome.cson (#244)

--- def/ru/welcome.cson
+++ def/ru/welcome.cson
@@ -1,7 +1,7 @@
 Welcome:
   tabTitle: "Добро пожаловать"
   subtitle: {
-    text1: "Хакабельный текстовый редактор 21"
+    text1: "Хакабельный текстовый редактор XXI"
     superscript: ""
     text2: " века"
   }


Comment out console.log() calls as IE barfs on them

--- demo/js/aura.coffee
+++ demo/js/aura.coffee
@@ -40,12 +40,12 @@
     plows = {}

 refresh_plows = (reset) ->
-    console.log "refresh"
+    #console.log "refresh"
     url = URL_BASE + '?' + plow_filter + '&callback=?'
     $.getJSON(url, (data) ->
         if reset
             reset_plows()
-        console.log "got data for #{ data.length } plows"
+        #console.log "got data for #{ data.length } plows"
         for plow_info in data
             if plow_info.id not of plows
                 plow = add_plow(plow_info)
@@ -56,7 +56,7 @@
                 old_ll = marker.getLatLng()
                 coords = plow_info.last_loc.coords
                 new_ll = new L.LatLng(coords[1], coords[0])
-                console.log "plow #{plow.id} moved " + new_ll.distanceTo(old_ll)
+                #console.log "plow #{plow.id} moved " + new_ll.distanceTo(old_ll)
                 marker.setLatLng(new_ll)
                 plow.last_loc = plow_info.last_loc

@@ -68,7 +68,7 @@
 show_plow_trail = (plow) ->
     url = URL_BASE + plow.id + '?history=500&callback=?'
     $.getJSON(url, (data) ->
-        console.log "history for " + plow.id
+        #console.log "history for " + plow.id
         # First remove all other trails
         for plow_id of plows
             p = plows[plow_id]


dont do new date with null value

dont do new date with null value

--- src/flux/task-plan.coffee
+++ src/flux/task-plan.coffee
@@ -342,17 +342,16 @@
     getOpensAt: (id, periodId) ->
       if periodId?
         tasking = @_getPeriodDates(id, periodId)
-        new Date(tasking?.opens_at)
-      else
-        # default opens_at to 1 day from now
-        @_getTaskingsCommonDate(id, 'opens_at')
+        opensAt = new Date(tasking?.opens_at) if tasking?.opens_at?
+
+      opensAt ?= @_getTaskingsCommonDate(id, 'opens_at')

     getDueAt: (id, periodId) ->
       if periodId?
         tasking = @_getPeriodDates(id, periodId)
-        new Date(tasking?.due_at)
-      else
-        @_getTaskingsCommonDate(id, 'due_at')
+        dueAt = new Date(tasking?.due_at) if tasking?.due_at?
+
+      dueAt ?= @_getTaskingsCommonDate(id, 'due_at')

     hasTasking: (id, periodId) ->
       plan = @_getPlan(id)


improve logging

improve logging

--- services/notifications/app/coffee/HealthCheckController.coffee
+++ services/notifications/app/coffee/HealthCheckController.coffee
@@ -34,7 +34,7 @@
 					if hasNotification
 						cb(null, body)
 					else
-						logger.log body:body, "Health Check: got notifications response for health check"
+						logger.err body:body, notification_key:notification_key, "Health Check: notification not in response"
 						return cb("notification not found in response")
 		]
 		async.series jobs, (err, body)->


add metric for applied-ops events

add metric for applied-ops events

--- services/real-time/app/coffee/DocumentUpdaterController.coffee
+++ services/real-time/app/coffee/DocumentUpdaterController.coffee
@@ -15,6 +15,7 @@
 	listenForUpdatesFromDocumentUpdater: (io) ->
 		rclient.subscribe "applied-ops"
 		rclient.on "message", (channel, message) ->
+			metrics.inc "rclient", 0.001 # global event rate metric
 			EventLogger.debugEvent(channel, message) if settings.debugEvents > 0
 			DocumentUpdaterController._processMessageFromDocumentUpdater(io, channel, message)


Bugfix

Bugfix

--- cake/tasks.coffee
+++ cake/tasks.coffee
@@ -82,7 +82,7 @@
     test:
       command:      'del:test'
       description:  'Delete a Mocha test file\n'
-      task:         -> do Scaffold.Test.generate
+      task:         -> do Scaffold.Test.destroy

   build:
     once:


`Element.Emitter::disconnect` optimizations

--- Element/emitter.coffee
+++ Element/emitter.coffee
@@ -52,11 +52,12 @@
 				index = events.indexOf func, index
 				if index is -1 or events[index+1] is ctx
 					break
-				++index
+				index += 2
 			assert.isNot index, -1

-			currentEmitter._events[id][index] = null
-			currentEmitter._events[id][index+1] = null
+			events[index] = null
+			events[index+1] = null
+
 			return

 		getter = ->


Move report filtering out of the list method

--- src/reporter.coffee
+++ src/reporter.coffee
@@ -47,30 +47,47 @@
     , @

     reports.forEach (r) -> r.date = helper.format_date r.date
-
-    if options?
-      if options.type?
-        impetus = ['button', 'buttonAsleep', 'notification', 'sleep', 'wake']
-        reports = reports.filter (r) ->
-          r.reportImpetus? and r.reportImpetus == impetus.indexOf options.type
-
-      if options.connection?
-        connections = ['cellular', 'wifi', 'none']
-        reports = reports.filter (r) ->
-          r.connection == connections.indexOf options.connection
-
-      if options.date?
-        reports = reports.filter (r) ->
-          reportDate = new Date(r.date)
-          reportDate.toDateString() == options.date.toDateString()
-
-      if options.between? and options.between.start? and options.between.end?
-        reports = reports.filter (r) ->
-          reportDate = new Date(r.date)
-          +reportDate >= +options.between.start and +reportDate <= +options.between.end
+    reports = reportFilter(reports, options)

     if cb?
       cb null, reports
     else
       reports
 ).call(Reports.prototype)
+
+# Private: Filter reports.
+#
+# reports - The reports to filter.
+#
+# options - The Hash options to filter the results by (default: {}):
+#           :type - The type of notifications (default: all):
+#             ['button', 'buttonAsleep', 'notification', 'sleep', 'wake']
+#           :connection - The network connection of the device when the
+#             report was made (default: all), ['cellular', 'wifi', 'none']
+#           :date - A Date object (default: none)
+#           :between - Interval in between the report(s) is (are).
+#
+# Returns an array containing the filtered reports.
+reportFilter = (reports, options) ->
+  if options?
+    if options.type?
+      impetus = ['button', 'buttonAsleep', 'notification', 'sleep', 'wake']
+      reports = reports.filter (r) ->
+        r.reportImpetus? and r.reportImpetus == impetus.indexOf options.type
+
+    if options.connection?
+      connections = ['cellular', 'wifi', 'none']
+      reports = reports.filter (r) ->
+        r.connection == connections.indexOf options.connection
+
+    if options.date?
+      reports = reports.filter (r) ->
+        reportDate = new Date(r.date)
+        reportDate.toDateString() == options.date.toDateString()
+
+    if options.between? and options.between.start? and options.between.end?
+      reports = reports.filter (r) ->
+        rDate = new Date(r.date)
+        +rDate >= +options.between.start and +rDate <= +options.between.end
+
+  reports


Only render if profile_url is present

Only render if profile_url is present

--- src/components/navbar/account-link.cjsx
+++ src/components/navbar/account-link.cjsx
@@ -15,6 +15,7 @@
       window.location.href = CurrentUserStore.getProfileUrl()

   render: ->
+    return null unless CurrentUserStore.getProfileUrl()
     <BS.MenuItem onSelect={@redirectToAccount} >
       My Account
     </BS.MenuItem>


fixes

fixes

--- run.coffee
+++ run.coffee
@@ -21,8 +21,8 @@
   process.exit 1

 if argv.i
-  p magenta "Input:", cyan.bold process.argv[2]
-await tokenize  process.argv[2], {}, defer err, tok_res
+  p magenta "Input:", cyan.bold argv._[0]
+await tokenize argv._[0], {}, defer err, tok_res
 throw err if err
 if argv.t
   p "Token list:"


Put back GitRepository::isDestroyed() method

--- src/git-repository.coffee
+++ src/git-repository.coffee
@@ -116,6 +116,10 @@
     if @subscriptions?
       @subscriptions.dispose()
       @subscriptions = null
+
+  # Public: Returns a {Boolean} indicating if this repository has been destroyed.
+  isDestroyed: ->
+    not @repo?

   # Public: Invoke the given callback when this GitRepository's destroy() method
   # is invoked.


[FIX] Selector on toc smooth scroll

[FIX] Selector on toc smooth scroll

--- app/assets/javascripts/totem/lodestar/modules/table_of_content.coffee
+++ app/assets/javascripts/totem/lodestar/modules/table_of_content.coffee
@@ -5,10 +5,11 @@

   smooth_scroll: (options) ->
     speed = options['speed']
-    $('a[href^="#"]').on 'click', (e) ->
+    $('.toc_list').children().on 'click', (e) ->
       e.preventDefault()
       target = @hash
       $target = $(target)
+      console.log 'Target', $target
       $('html, body').stop().animate { 'scrollTop': $target.offset().top }, speed, 'swing', ->
         window.location.hash = target
         return


Set router location to hash.

Set router location to hash.

--- app/assets/javascripts/voluntary_core_module_emberjs/router.js.coffee
+++ app/assets/javascripts/voluntary_core_module_emberjs/router.js.coffee
@@ -2,4 +2,4 @@
   @resource 'users'

 VoluntaryOnEmberjs.Router.reopen
-  location: 'history'+  location: 'hash'


change placeholder on hidden_field

change placeholder on hidden_field

--- src/scripts/fields/hidden_field.coffee
+++ src/scripts/fields/hidden_field.coffee
@@ -12,7 +12,7 @@
   edit: """

Data

     <textarea data-rv-input='model.<%= Formbuilder.options.mappings.DESCRIPTION %>'
-      placeholder='Add a longer description to this field'></textarea>
+      placeholder='Add some data to this hidden field'></textarea>
   """

   addButton: """


Activity : changed bounded method to refresh from populateActivity

--- client/landing/app/Applications/Activity.kdapplication/AppController.coffee
+++ client/landing/app/Applications/Activity.kdapplication/AppController.coffee
@@ -57,7 +57,7 @@
   loadView:->
     @getView().feedWrapper.ready (controller)=>
       @attachEvents @getView().feedWrapper.controller
-      @ready @bound "populateActivity"
+      @ready @bound "refresh"
     @emit 'ready'

   resetAll:->


Revert "Revert "fix bug where 'Everything' filter was brokern; comments weren't showing""

This reverts commit 614c3790d1688deaef7c7c8282fe3cd93f354b84.

--- client/landing/app/Applications/Activity.kdapplication/AppController.coffee
+++ client/landing/app/Applications/Activity.kdapplication/AppController.coffee
@@ -8,14 +8,7 @@
   {dash} = Bongo

   activityTypes = [
-    'CStatusActivity'
-    'CCodeSnipActivity'
-    'CFollowerBucketActivity'
-    'CNewMemberBucketActivity'
-    'CDiscussionActivity'
-    'CTutorialActivity'
-    'CInstallerBucketActivity'
-    'CBlogPostActivity'
+    'Everything'
   ]

   @clearQuotes = clearQuotes = (activities)->
@@ -115,19 +108,17 @@
     KD.time "Activity fetch took - "
     options = to : options.to or Date.now()

-    @fetchActivity options, (err, teasers)=>
+    @fetchCachedActivity options, (err, cache)=>
       @isLoading = no
-      @listController.hideLazyLoader()
-      KD.timeEnd "Activity fetch took"
-
-      if err or teasers.length is 0
-        warn "An error occured:", err  if err
+      if err or cache.length is 0
+        warn err  if err
+        @listController.hideLazyLoader()
         @listController.showNoItemWidget()
       else
-        @extractTeasersTimeStamps(teasers)
-        @listController.listActivities teasers
-
-      callback? err, teasers
+        @extractCacheTimeStamps cache
+        @sanitizeCache cache, (err, cache)=>
+          @listController.hideLazyLoader()
+          @listController.listActivitiesFromCache cache

   fetchActivitiesFromCache:(options = {})->
     @fetchCachedActivity options, (err, cache)=>
@@ -304,11 +295,13 @@
   fetchCachedActivity:(options = {}, callback)->
     if KD.config.useNeo4j
       options.timestamp or= options.to
-      options.groupName = KD.getSingleton("groupsController").getCurrentGroup()?.slug or "koding"
+      options.groupName   = KD.getSingleton("groupsController").getCurrentGroup()?.slug or "koding"
+      options.facets      = @getFilter()

       KD.remote.api.CStatusActivity.fetchPublicActivityFeed options, (err, result)=>
         result.overview.reverse() if result?.overview
         return callback err, result
+
     else
       $.ajax
         url     : "/-/cache/#{options.slug or 'latest'}"


IDE: Added saveAs method to AppController.

--- client/ide/AppController.coffee
+++ client/ide/AppController.coffee
@@ -338,6 +338,9 @@
   saveFile: ->
     @getActivePaneView().emit 'SaveRequested'

+  saveAs: ->
+    @getActivePaneView().aceView.ace.requestSaveAs()
+
   saveAllFiles: ->
     @forEachSubViewInIDEViews_ 'editor', (editorPane) ->
       editorPane.emit 'SaveRequested'


refactor the relevant implementation

refactor the relevant implementation

--- library/membrane/document.coffee
+++ library/membrane/document.coffee
@@ -133,11 +133,15 @@
     # is being described by this document. If you do no supply any
     # arguments this method will return already described failures.
     # The relevant should be a string that contains a valid URL.
-    relevant: (relevant) ->
-        return @$relevant if arguments.length is 0
-        notString = "a relevant should be a string"
-        assert _.all(relevant, _.isString), notString
+    # The invocation signature is splat, to natually suport vector.
+    relevant: (relevant...) ->
+        return @$relevant or [] if arguments.length is 0
+        internal = "an internal, implementational error"
+        typ = "all of the elements must be valid strings"
+        assert relevant and _.isArray(relevant), internal
+        assert _.all(relevant, _.isString), typ.toString()
         @$relevant = (@$relevant or []).concat relevant
+        @$relevant = _.toArray _.unique @$relevant or []
         @emit.call @, "relevant", @$relevant, arguments
         assert _.isArray @$relevant; return @$relevant

@@ -156,7 +160,7 @@
     # Either get or set the schemas information of the method that
     # is being described by this document. If you do no supply any
     # arguments this method will return already described failures.
-    # The schemas should be an object of `slot: schema` values.
+    # The schemas should be an object of the `slot: schema` values.
     schemas: (schemas) ->
         return @$schemas if arguments.length is 0
         noSchemas = "the schemas should be a object"


continued refactoring

continued refactoring

--- csi.coffee
+++ csi.coffee
@@ -216,7 +216,8 @@
   requirejs: (config) ->
     join config.baseUrl || "", config.paths.csi, "require.js"
   extra: () ->
-    stringBundlesAsRequirejsModule()
+    # stringBundlesAsRequirejsModule()
+    ''
   config: (config) ->
     JSON.stringify config, null, "    "
   optimizations: (config) ->
@@ -428,17 +429,22 @@
         provide argv.templatepath

         templateObj = configCommands.all config,
-          require: true
+          requirejs: true
           extra: true
           config: true
           baseurl: true
-        contextjsonname = join(argv.templatepath, argv.contextjsonname)
-        log "writing template context to #{contextjsonname}"
-        write contextjsonname, JSON.stringify(templateObj)
-
-        stringBundleName = join(argv.templatepath, "strings.yaml")
+        templateContextName = join argv.templatepath, "csi-template-context.json"
+        log "writing template context to #{templateContextName}"
+        write templateContextName, JSON.stringify(templateObj, null, "    ")
+
+        stringBundleName = join(argv.templatepath, "strings.json")
         log "writing string bundle to #{stringBundleName}"
         write stringBundleName, JSON.stringify(allStringBundles(), null, "    ")
+
+        contextObj = configCommands.all config, optimizations: true
+        contextName = join argv.templatepath, "csi-context.json"
+        log "writing context to #{contextName}"
+        write contextName, JSON.stringify(contextObj, null, "    ")

   completion:
     description: """


update label

update label

--- udo_framer/MODHome2018.framer/app.coffee
+++ udo_framer/MODHome2018.framer/app.coffee
@@ -346,9 +346,9 @@
 	name:"BTN_Child"
 	value:"2+好片上架！"},{
 	name:"BTN_Sporteee"
-	value:"春番新上架！"},{
+	value:"FIFA運動影音"},{
 	name:"BTN_Comicss"
-	value:"FIFA運動影音"}]
+	value:"春番新上架！"}]
 TVBtnsLabelArray=[{
 	name:"ADDBTN"
 	value:"增加捷徑"},{


cassandra --> rethink: blobs

cassandra --> rethink: blobs

--- salvus/cassandra.coffee
+++ salvus/cassandra.coffee
@@ -3158,6 +3158,12 @@
             delete opts.cb

     r_accounts: (cb) =>
+        cb("todo");return
+        # TODO:
+        # - when migrating projects, `settings.disk --> settings.disk_quota (with factor of 1.5)`
+        # - when migrating projects, `if quotas.memory < 70 then quotas.memory *= 1000`
+        # - project settings network: ` if typeof(opts.network) == 'string' and opts.network == 'false'; # this is messed up in the database due to bad client code...`
+
         table = require('rethink').rethinkdb().table('accounts')
         cols = ['account_id', 'created', 'password_hash',
                'first_name', 'last_name', 'email_address',
@@ -3183,6 +3189,17 @@
     r_account_creation_actions: (cb) =>

     r_blobs: (cb) =>
+        table = require('rethink').rethinkdb().table('blobs')
+        @dump_table
+            table : 'uuid_blob'
+            columns : ['uuid', 'value']
+            where   : {name:'blobs'}
+            #limit   : 2000
+            each    : (row, cb) ->
+                #console.log("each...", row.uuid, "blob.length=", row.value.length)
+                # we remove all expires... (i.e., don't set them so infinite)
+                table.insert({id:row.uuid, blob:row.value}).run(cb)
+            cb      : cb

     r_central_log: (cb) =>
         table = require('rethink').rethinkdb().table('central_log')


remove disable no_implicit_braces statement in guestcleanerworker

--- workers/guestcleaner/lib/guestcleaner/guestcleanerwoker.coffee
+++ workers/guestcleaner/lib/guestcleaner/guestcleanerwoker.coffee
@@ -9,8 +9,6 @@

   whitlistedModels = ['JSession', 'JUser', 'JProposedDomain', 'JAppStorage', 'JName']

-  # due to a bug in coffeelint 1.10.1
-  # coffeelint: disable=no_implicit_braces
   collectDataAndRelationships: (relationships, callback) ->
     toBeDeletedData = {}
     toBeDeletedRelationshipIds = []


remove logging

remove logging

--- shared/ironTableController.coffee
+++ shared/ironTableController.coffee
@@ -25,7 +25,7 @@
         # Set Up Edit Path
         editRoutePath = @route.originalPath.replace(/\/[^\/]+$/ , '') + "/edit/:_id"
         editRouteName = @collection()._name + 'Edit'
-        console.log("editPath", editRoutePath)
+        #console.log("editPath", editRoutePath)

         Router.map ->
             @route editRouteName,
@@ -156,7 +156,7 @@
         col = @_cols()[filterColumn]
         if filterColumn and filterColumn isnt "_none_" and col and filterValue isnt ''
             dataKey = col.dataKey or filterColumn
-            console.log("have filter", filterColumn, dataKey, filterValue)
+            #console.log("have filter", filterColumn, dataKey, filterValue)
             select[dataKey] =
                 $regex: ".*#{filterValue}.*"
                 $options: 'i'


update a11y extension so it loads same version as mathjax

--- shared/src/helpers/mathjax.coffee
+++ shared/src/helpers/mathjax.coffee
@@ -64,7 +64,7 @@
     window.MathJax.Hub.Configured()

   if window.MathJax?.Hub
-    window.MathJax.Ajax.config.path["a11y"] = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/extensions/a11y"
+    window.MathJax.Ajax.config.path["a11y"] = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/#{window.MathJax.version}/extensions/a11y"
     window.MathJax.Hub.Config(MATHJAX_CONFIG)
     # Does not seem to work when passed to Config
     window.MathJax.Hub.processSectionDelay = 0


Patching the coffee's 'void 0' hack back to the 'undefined' value

--- cli/source.coffee
+++ cli/source.coffee
@@ -29,13 +29,19 @@

   # converting coffee into javascript if needed
   if format is 'coffee'
+    source = require('coffee-script').compile(source)
+
+    # fixing coffee's void(0) hack back to `undefined`
+    source = source.replace(/^\(function\(\)\s*\{/, '(function(undefined) {')
+    source = source.replace(/([^a-z0-9\_]+)void\s+0([^a-z0-9]+)/ig, '$1undefined$2')
+
     source = """
     /**
      * lovely.io '#{options.name}' module v#{options.version}
      *
      * Copyright (C) #{new Date().getFullYear()} #{options.author}
      */
-    #{require('coffee-script').compile(source)}
+    #{source}
     """

   # adding the package options


member list: DRY fetching following/followers from graph

--- workers/social/lib/social/models/account/index.coffee
+++ workers/social/lib/social/models/account/index.coffee
@@ -967,10 +967,16 @@
     oldAddTags.call this, client, tags, options, callback

   fetchMyFollowingsFromGraph: secure (client, options, callback)->
+    @fetchFollowFromGraph "fetchFollowingMembers", client, options, callback
+
+  fetchMyFollowersFromGraph: secure (client, options, callback)->
+    @fetchFollowFromGraph "fetchFollowerMembers", client, options, callback
+
+  fetchFollowFromGraph: secure (followType, client, options, callback)->
     graph = new Graph({config:KONFIG['neo4j']})
     userId = client.connection.delegate._id
     options.currentUserId = userId
-    graph.fetchFollowingMembers options, (err, results)=>
+    graph[followType] options, (err, results)=>
       if err then return callback err
       else
         tempRes = []
@@ -987,28 +993,3 @@
           callback null, tempRes
         for res in results
           collectContents res
-
-
-  fetchMyFollowersFromGraph: secure (client, options, callback)->
-    graph = new Graph({config:KONFIG['neo4j']})
-    userId = client.connection.delegate._id
-    options.currentUserId = userId
-    graph.fetchFollowerMembers options, (err, results)=>
-      if err then return callback err
-      else
-        tempRes = []
-        collectContents = race (i, res, fin)=>
-          objId = res.id
-          JAccount.one  { _id : objId }, (err, account)=>
-            if err
-              callback err
-              fin()
-            else
-              tempRes[i] =  account
-              fin()
-        , ->
-          callback null, tempRes
-        for res in results
-          collectContents res
-
-


Clear SEO

Clear SEO

--- seo.coffee
+++ seo.coffee
@@ -1,6 +1,6 @@
 if Meteor.isServer
   Meteor.startup ->
-    SeoCollection.remove()
+    SeoCollection.remove({})
     stdog =
       'title': 'Dota 2 Modding',
       'image': 'http://d2modd.in/images/D2Logo.png'


Fix deprecated syntax API

Fix deprecated syntax API

--- spec/asciidoc-spec.coffee
+++ spec/asciidoc-spec.coffee
@@ -6,7 +6,7 @@
       atom.packages.activatePackage("language-asciidoc")

     runs ->
-      grammar = atom.syntax.grammarForScopeName("source.asciidoc")
+      grammar = atom.grammars.grammarForScopeName("source.asciidoc")

   it "parses the grammar", ->
     expect(grammar).toBeDefined()


Update downloadMaterials.coffee

Update downloadMaterials.coffee

--- server/cron/downloadMaterials.coffee
+++ server/cron/downloadMaterials.coffee
@@ -698,8 +698,7 @@
             a.href = newhref
             a.setAttribute("onclick", "window.goto('#{newhref}')();return false;")
         body = document.getElementsByTagName("body")[0]
-        material.content = body.innerHTML
-
+        material.content = body.innerHTML
     correctInternalLinks: ->
         promises = []
         for id, material of @materials


不要な読込

不要な読込

--- src/js/libs/Config.coffee
+++ src/js/libs/Config.coffee
@@ -1,7 +1,6 @@
 import {readFile} from 'fs'
 import {normalize} from 'path'
 import {safeLoad} from 'js-yaml'
-import {AppState} from '../reducers'
 import {configLoad, authSetup} from '../actions'

 # コンフィグクラス


Close on esc

Close on esc

--- SingularityUI/app/components/aggregateTail/Header.cjsx
+++ SingularityUI/app/components/aggregateTail/Header.cjsx
@@ -12,9 +12,10 @@
     @props.setSearch(@state.searchVal)

   handleKeyPress: (event) ->
-    console.log event.keyCode
-    if event.keyCode is 13
+    if event.keyCode is 13 # Enter: commit search and close
       @setSearch()
+      $("#searchDDToggle").dropdown("toggle")
+    else if event.keyCode is 27 # Escape: close without committing
       $("#searchDDToggle").dropdown("toggle")

   renderBreadcrumbs: ->


bongo: throwIt should be written competently

--- node_modules_koding/bongo/lib/bongo.coffee
+++ node_modules_koding/bongo/lib/bongo.coffee
@@ -63,9 +63,9 @@

   Client = require './client'

-  @throwIt =(it)->
-    throw it  if it?
-    process.exit process.pid, 'SIGTERM'
+  @throwIt = (it) ->
+    console.error it  if it?
+    process.kill process.pid, 'SIGTERM'

   constructor:(options)->
     {@mq, @mongo, @resourceName, @root, @fetchClient, models} = options


bongo: emit a more helpful error when failing to load a class

--- node_modules_koding/bongo/lib/bongo.coffee
+++ node_modules_koding/bongo/lib/bongo.coffee
@@ -123,7 +123,11 @@
     @registry = @createModelRegistry(modelPath)
     @registry.forEach (path)=>
       try model = require path
-      catch e then return @emit 'error', e
+      catch e
+        err = new Error
+        err.originalError = e
+        err.message = "Error loading a class: #{path}"
+        return @emit 'error', err
       if model.name? and ('function' is typeof model)
         @defineModel model.name, model
       else
@@ -131,7 +135,7 @@
       @registry.setState path, READY
     @emit 'ready'

-  getInstanceRoutingKey =(inst, event)->
+  getInstanceRoutingKey =(inst, event)->
     "oid.#{inst.getId()}.event.#{event}"

   getStaticRoutingKey =(konstructor, event)->


Pass given client argument to method

Pass given client argument to method

--- node_modules_koding/bongo/lib/bongo.coffee
+++ node_modules_koding/bongo/lib/bongo.coffee
@@ -368,7 +368,7 @@
         fn.autoCull = yes
         @remoteStore.add storeKey, fn
       @remoteStore.get storeKey
-    @invokeMethod method, unscrubbed, userArea, sessionToken, secretName
+    @invokeMethod method, unscrubbed, userArea, sessionToken, secretName, client

   pong:(callback)-> callback? Date.now()


:lipstick:

:lipstick:

--- spec/atom/editor-spec.coffee
+++ spec/atom/editor-spec.coffee
@@ -35,7 +35,6 @@
       expect(mainDiv.children('.editor').length).toBe 0

   describe "open(url)", ->
-
     describe "when called with a url", ->
       it "loads a buffer for the given url into the editor", ->
         editor.open(filePath)


Allow category override and colour override

--- src/languages/html.coffee
+++ src/languages/html.coffee
@@ -5,142 +5,151 @@

 ATTRIBUTE_CLASSES = ['#attribute']

-COLORS = {
+TAGS = {
   #Metadata
-  '#documentType': 'lightblue'
-  html: 'lightblue'
-  head: 'lightblue'
-  body: 'lightblue'
-  title: 'lightblue'
-  link: 'lightblue'
-  meta: 'lightblue'
-  style: 'lightblue'
-  script: 'lightblue'
-  base: 'lightblue'
+  '#documentType': {category: 'metadata'}
+  html: {category: 'metadata'}
+  head: {category: 'metadata'}
+  title: {category: 'metadata'}
+  link: {category: 'metadata'}
+  meta: {category: 'metadata'}
+  style: {category: 'metadata'}
+  script: {category: 'metadata'}
+  base: {category: 'metadata'}

   #Grouping
-  p: 'purple'
-  h1: 'purple'
-  h2: 'purple'
-  h3: 'purple'
-  h4: 'purple'
-  h5: 'purple'
-  h6: 'purple'
-  hr: 'purple'
-  div: 'purple'
-  span: 'purple'
-  ul: 'purple'
-  ol: 'purple'
-  li: 'purple'
-  dl: 'purple'
-  dt: 'purple'
-  dd: 'purple'
-  pre: 'purple'
-  blockquote: 'purple'
-  figure: 'purple'
-  figcaption: 'purple'
-  main: 'purple'
-  dd: 'purple'
+  p: {category: 'grouping'}
+  hr: {category: 'grouping'}
+  div: {category: 'grouping'}
+  ul: {category: 'grouping'}
+  ol: {category: 'grouping'}
+  li: {category: 'grouping'}
+  dl: {category: 'grouping'}
+  dt: {category: 'grouping'}
+  dd: {category: 'grouping'}
+  pre: {category: 'grouping'}
+  blockquote: {category: 'grouping'}
+  figure: {category: 'grouping'}
+  figcaption: {category: 'grouping'}
+  main: {category: 'grouping'}
+  dd: {category: 'grouping'}

   #Content
-  a: 'lightgreen'
-  img: 'lightgreen'
-  iframe: 'lightgreen'
-  i: 'lightgreen'
-  b: 'lightgreen'
-  u: 'lightgreen'
-  sub: 'lightgreen'
-  sup: 'lightgreen'
-  br: 'lightgreen'
-  em: 'lightgreen'
-  strong: 'lightgreen'
-  small: 'lightgreen'
-  s: 'lightgreen'
-  cite: 'lightgreen'
-  q: 'lightgreen'
-  dfn: 'lightgreen'
-  abbr: 'lightgreen'
-  ruby: 'lightgreen'
-  rt: 'lightgreen'
-  rp: 'lightgreen'
-  data: 'lightgreen'
-  time: 'lightgreen'
-  code: 'lightgreen'
-  var: 'lightgreen'
-  samp: 'lightgreen'
-  kbd: 'lightgreen'
-  mark: 'lightgreen'
-  bdi: 'lightgreen'
-  bdo: 'lightgreen'
-  wbr: 'lightgreen'
-  '#text': 'lightgreen'
+  a: {category: 'content'}
+  i: {category: 'content'}
+  b: {category: 'content'}
+  u: {category: 'content'}
+  sub: {category: 'content'}
+  sup: {category: 'content'}
+  br: {category: 'content'}
+  em: {category: 'content'}
+  strong: {category: 'content'}
+  small: {category: 'content'}
+  s: {category: 'content'}
+  cite: {category: 'content'}
+  q: {category: 'content'}
+  dfn: {category: 'content'}
+  abbr: {category: 'content'}
+  ruby: {category: 'content'}
+  rt: {category: 'content'}
+  rp: {category: 'content'}
+  data: {category: 'content'}
+  time: {category: 'content'}
+  code: {category: 'content'}
+  var: {category: 'content'}
+  samp: {category: 'content'}
+  kbd: {category: 'content'}
+  mark: {category: 'content'}
+  bdi: {category: 'content'}
+  bdo: {category: 'content'}
+  span: {category: 'content'}
+  wbr: {category: 'content'}
+  '#text': {category: 'content'}

   #Sections
-  article: 'orange'
-  section: 'orange'
-  nav: 'orange'
-  aside: 'orange'
-  hgroup: 'orange'
-  header: 'orange'
-  footer: 'orange'
-  address: 'orange'
+  body: {category: 'sections'}
+  article: {category: 'sections'}
+  section: {category: 'sections'}
+  nav: {category: 'sections'}
+  aside: {category: 'sections'}
+  h1: {category: 'sections'}
+  h2: {category: 'sections'}
+  h3: {category: 'sections'}
+  h4: {category: 'sections'}
+  h5: {category: 'sections'}
+  h6: {category: 'sections'}
+  hgroup: {category: 'sections'}
+  header: {category: 'sections'}
+  footer: {category: 'sections'}
+  address: {category: 'sections'}

   #Table
-  table: 'indigo'
-  caption: 'indigo'
-  colgroup: 'indigo'
-  col: 'indigo'
-  tbody: 'indigo'
-  thead: 'indigo'
-  tfoot: 'indigo'
-  tr: 'indigo'
-  td: 'indigo'
-  th: 'indigo'
+  table: {category: 'table'}
+  caption: {category: 'table'}
+  colgroup: {category: 'table'}
+  col: {category: 'table'}
+  tbody: {category: 'table'}
+  thead: {category: 'table'}
+  tfoot: {category: 'table'}
+  tr: {category: 'table'}
+  td: {category: 'table'}
+  th: {category: 'table'}

   #Form
-  form: 'deeporange'
-  input: 'deeporange'
-  textarea: 'deeporange'
-  label: 'deeporange'
-  button: 'deeporange'
-  select: 'deeporange'
-  option: 'deeporange'
-  optgroup: 'deeporange'
-  datalist: 'deeporange'
-  keygen: 'deeporange'
-  output: 'deeporange'
-  progress: 'deeporange'
-  meter: 'deeporange'
-  fieldset: 'deeporange'
-  legend: 'deeporange'
+  form: {category: 'form'}
+  input: {category: 'form'}
+  textarea: {category: 'form'}
+  label: {category: 'form'}
+  button: {category: 'form'}
+  select: {category: 'form'}
+  option: {category: 'form'}
+  optgroup: {category: 'form'}
+  datalist: {category: 'form'}
+  keygen: {category: 'form'}
+  output: {category: 'form'}
+  progress: {category: 'form'}
+  meter: {category: 'form'}
+  fieldset: {category: 'form'}
+  legend: {category: 'form'}

   #Embedded
-  embed: 'teal'
-  object: 'teal'
-  param: 'teal'
-  video: 'teal'
-  audio: 'teal'
-  source: 'teal'
-  track: 'teal'
-  map: 'teal'
-  area: 'teal'
+  img: {category: 'embedded'}
+  iframe: {category: 'embedded'}
+  embed: {category: 'embedded'}
+  object: {category: 'embedded'}
+  param: {category: 'embedded'}
+  video: {category: 'embedded'}
+  audio: {category: 'embedded'}
+  source: {category: 'embedded'}
+  track: {category: 'embedded'}
+  map: {category: 'embedded'}
+  area: {category: 'embedded'}

   #Other known tags
-  ins: 'pink'
-  del: 'pink'
-  details: 'pink'
-  summary: 'pink'
-  menu: 'pink'
-  menuitem: 'pink'
-  dialog: 'pink'
-  noscript: 'pink'
-  template: 'pink'
-  canvas: 'pink'
-  svg: 'pink'
-  frameset: 'pink'
-
-  #Unknow tag fallback
-  'Default': 'yellow'
+  ins: {category: 'other'}
+  del: {category: 'other'}
+  details: {category: 'other'}
+  summary: {category: 'other'}
+  menu: {category: 'other'}
+  menuitem: {category: 'other'}
+  dialog: {category: 'other'}
+  noscript: {category: 'other'}
+  template: {category: 'other'}
+  canvas: {category: 'other'}
+  svg: {category: 'other'}
+  frameset: {category: 'other'}
+}
+
+CATEGORIES = {
+  metadata: {color: 'lightblue'}
+  grouping: {color: 'purple'}
+  content: {color: 'lightgreen'}
+  sections: {color: 'orange'}
+  table: {color: 'indigo'}
+  form: {color: 'deeporange'}
+  embedded: {color: 'teal'}
+  other: {color: 'pink'}
+  Default: {color: 'yellow'}
 }

 DEFAULT_INDENT_DEPTH = '  '
@@ -178,6 +187,10 @@

   constructor: (@text, @opts = {}) ->
     super
+
+    @opts.tags = helper.extend({}, TAGS, @opts.tags)
+    @opts.categories = helper.extend({}, CATEGORIES, @opts.categories)
+
     @lines = @text.split '\n'

   getPrecedence: (node) -> 1
@@ -191,7 +204,9 @@
     return classes

   getColor: (node) ->
-    COLORS[node.nodeName] ? COLORS['Default']
+    if @opts.tags[node.nodeName]
+      return @opts.categories[@opts.tags[node.nodeName].category].color
+    return @opts.categories.Default.color

   getBounds: (node) ->
     bounds = {


Unmock clock when running specs in atom

Unmock clock when running specs in atom

--- spec/text-buffer-spec.coffee
+++ spec/text-buffer-spec.coffee
@@ -10,6 +10,10 @@

 describe "TextBuffer", ->
   buffer = null
+
+  beforeEach ->
+    # When running specs in Atom, setTimeout is spied on by default.
+    jasmine.useRealClock?()

   afterEach ->
     buffer = null


Refactor flash JS

Refactor flash JS

--- app/assets/javascripts/neighborly/neighborly.js.coffee
+++ app/assets/javascripts/neighborly/neighborly.js.coffee
@@ -31,11 +31,10 @@
   init: ->
     $(document).foundation('reveal', {animation: 'fadeAndPop', animationSpeed: 100})
     $(document).foundation()
+    this.flash.init()

     $.pjax.defaults.scrollTo = false if $.pjax.defaults?
     $.pjax.defaults.timeout = false if $.pjax.defaults?
-
-    this.flash()

     $('.button.disabled').click ->
       return false
@@ -54,13 +53,14 @@
     hide: ->
       $('#loading').removeClass('show')

-  flash: ->
-    if $(".flash").length > 0
-      this.flash_time_out = setTimeout this.closeFlash, 5000
-      $(".flash a.close").click(this.closeFlash)
+  flash:
+    init: ->
+      if $(".flash").length > 0
+        this.flash_time_out = setTimeout(this.close, 5000)
+        $(".flash a.close").click(this.close)

-  closeFlash: ->
-    $('.flash .alert-box').fadeOut('fast')
-    setTimeout (->
-      $('.flash').slideUp('slow')
-    ), 100
+    close: ->
+      $('.flash .alert-box').fadeOut('fast')
+      setTimeout (->
+        $('.flash').slideUp('slow')
+      ), 100


Correct pressstart2p font name

Correct pressstart2p font name

--- app/assets/javascripts/strut_builder/textbox.js.coffee
+++ app/assets/javascripts/strut_builder/textbox.js.coffee
@@ -1,7 +1,7 @@
 window.StrutBuilder ||= {}

 StrutBuilder.Textbox = {}
-faces = [ 'Lato', 'League Gothic, sans-serif', 'Droid Sans Mono, monospace', 'Ubuntu, sans-serif', 'Abril Fatface, cursive', 'Hammersmith One, sans-serif', 'Fredoka One, cursive', 'Gorditas, cursive', 'Press Start 2P, cursive' ]
+faces = [ 'Lato', 'League Gothic, sans-serif', 'Droid Sans Mono, monospace', 'Ubuntu, sans-serif', 'Abril Fatface, cursive', 'Hammersmith One, sans-serif', 'Fredoka One, cursive', 'Gorditas, cursive', 'PressStart2P, cursive' ]
 randomFace = ->
   faces[Math.floor(Math.random() * faces.length)]
 StrutBuilder.Textbox.build = (data, i) ->


Small fix

Small fix

--- scripts/virginie.coffee
+++ scripts/virginie.coffee
@@ -19,7 +19,7 @@
 quotes = [
   "ce que j'ecriver avant kje lecriver dans mon editeur de texte  enfin du moin je croyais lol",
   "une fois que jai t new requests je fork",
-  "Benoit: tu as pas le lien de ton github ? virginie: https://github.com/",
+  "Benoit tu as pas le lien de ton github ? virginie: https://github.com/",
   "jla j'espere que sa va fonctionnais que je puisse commencer les commencers les cours arf",
   "limite que je pende l'ordi mais j'y suis arriver xd",
   "pour sa rien a fonctionnais",


cosmetic change

cosmetic change

--- src/typetalk.coffee
+++ src/typetalk.coffee
@@ -1,12 +1,10 @@
 HTTPS          = require 'https'
 Request        = require 'request'
 {EventEmitter} = require 'events'
+Package        = require '../package'
+Hubot          = require 'hubot'

-Robot         = (require 'hubot').Robot
-Adapter       = (require 'hubot').Adapter
-TextMessage   = (require 'hubot').TextMessage
-
-class Typetalk extends Adapter
+class Typetalk extends Hubot.Adapter
   # override
   send: (envelope, strings...) ->
     for string in strings


added user agent headers

added user agent headers

--- src/typetalk.coffee
+++ src/typetalk.coffee
@@ -80,6 +80,8 @@
         client_secret: @clientSecret
         grant_type: 'client_credentials'
         scope: 'my,topic.read,topic.post'
+      headers:
+        'User-Agent': "#{Package.name} v#{Package.version}"

     Request.post options, (err, res, body) =>
       if err
@@ -114,6 +116,7 @@
         method: method
         headers:
           Authorization: "Bearer #{@accessToken}"
+          'User-Agent': "#{Package.name} v#{Package.version}"

       if method is 'POST'
         options.form = body


change default color to #c0c0c0 on JSView

--- JSKit/02_JSView.coffee
+++ JSKit/02_JSView.coffee
@@ -8,7 +8,7 @@
         super()
         @_parent = null
         @_viewSelector = "#"+@_objectID
-        @_bgColor = JSColor("#f0f0f0")
+        @_bgColor = JSColor("#c0c0c0")
         @_alpha = 1.0
         @_cornerRadius = 0
         @_borderColor = JSColor("clearColor")


add error catch to settings.defaults

add error catch to settings.defaults

--- services/clsi/config/settings.defaults.coffee
+++ services/clsi/config/settings.defaults.coffee
@@ -44,8 +44,8 @@
 	try
 		seccomp_profile_path = Path.resolve(__dirname + "/../seccomp/clsi-profile.json")
 		module.exports.clsi.seccomp_profile = JSON.stringify(JSON.parse(require("fs").readFileSync(seccomp_profile_path)))
-	catch
-		console.log "could not load seccom profile from #{seccomp_profile_path}"
+	catch error
+		console.log error, "could not load seccom profile from #{seccomp_profile_path}"

 	module.exports.path.synctexBaseDir = -> "/compile"


Fix reference book selectors

Fix reference book selectors

--- test-integration/reference-book.coffee
+++ test-integration/reference-book.coffee
@@ -5,7 +5,7 @@
 SERVER_URL = process.env['SERVER_URL'] or 'http://localhost:3001/'
 TEACHER_USERNAME = 'teacher01'

-SECTIONS_TO_TEST = 10
+SECTIONS_TO_TEST = 5

 describe 'Reference Book Exercises', ->

@@ -15,7 +15,6 @@
     checkForMissingExercises = =>
       # Wait until the book has loaded.
       @addTimeout(60)
-      wait(@).for(css: '.page-wrapper .page.has-html')
       wait(@).click(css: '.menu-toggle')

       doneLoading = =>
@@ -24,24 +23,23 @@

       for i in [1..SECTIONS_TO_TEST]
         # Selenium sometimes keeps pressing the same next button (doneLoading doesn't seem to work 100%)
-        @driver.findElement(css: 'a.nav.next').getAttribute('href').then (oldHref) =>
+        @driver.findElement(css: 'a.page-navigation.next').getAttribute('href').then (oldHref) =>
           @addTimeout(3)
-          console.log '----------------'
-          # console.log 'old ashkd', oldHref
-          @driver.findElement(css: 'a.nav.next').click()
+
+          @driver.findElement(css: 'a.page-navigation.next').click()

           @driver.wait(doneLoading)
-          # @driver.findElement(css: 'a.nav.next').getAttribute('href').then (foo) =>
+          # @driver.findElement(css: 'a.page-navigation.next').getAttribute('href').then (foo) =>
           #   console.log 'new ashkd', foo

           checkPageChanged = =>
-            @driver.findElement(css: 'a.nav.next').getAttribute('href').then (newHref) =>
+            @driver.findElement(css: 'a.page-navigation.next').getAttribute('href').then (newHref) =>
               newHref isnt oldHref

           ifPageDidntChange = =>
             @addTimeout(3)
             console.log 'Page did not change. reclicking.'
-            @driver.findElement(css: 'a.nav.next').click()
+            @driver.findElement(css: 'a.page-navigation.next').click()
             @driver.wait(doneLoading)

           @driver.wait(checkPageChanged, 1000).then(null, ifPageDidntChange)


#195 changed url

#195 changed url

--- app/assets/javascripts/admin/models/task/task_collection.coffee
+++ app/assets/javascripts/admin/models/task/task_collection.coffee
@@ -5,1390 +5,5 @@

 class TaskCollection extends PaginationCollection

-  url : "/api/user" #CHANGEME
+  url : "/api/tasks"

-  parse : ->
-    return [
-      {
-        "id":"52ff30077800009b0018ae65",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"18ae65",
-        "seedIdHeidelberg":0,
-        "projectName":"",
-        "type":{
-          "summary":"ek_0563_BipolarCells",
-          "description":"Check those cells out!",
-          "expectedTime":{
-            "min":5,
-            "max":10,
-            "maxHard":15
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis",
-              "arbitrary"
-            ],
-            "branchPointsAllowed":true,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"52ff2ff6780000780018ae64"
-          }
-        },
-        "dataSet":"2012-11-23_ex144_st08x2",
-        "editPosition":[
-          0,
-          0,
-          0
-        ],
-        "neededExperience":{
-          "domain":"",
-          "value":0
-        },
-        "priority":100,
-        "created":"2014-02-15 17:14",
-        "status":{
-          "open":9,
-          "inProgress":1,
-          "completed":0
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"50f932cbe4b00551ae7b9d12",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7b9d12",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":7,
-          "inProgress":0,
-          "completed":33
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"50fd1cb7e4b04e9323f742d4",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"f742d4",
-        "seedIdHeidelberg":0,
-        "projectName":"",
-        "type":{
-          "summary":"VideoTask",
-          "description":"Tracing Tasks that are used to demonstrate Oxalis in an introduction video",
-          "expectedTime":{
-            "min":5,
-            "max":10,
-            "maxHard":15
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis",
-              "arbitrary"
-            ],
-            "branchPointsAllowed":true,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"50fd1c80e4b04e9323f742d1"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"intro",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":196,
-          "inProgress":0,
-          "completed":4
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9e55e4b0d636137ff023",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff023",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":15,
-          "inProgress":0,
-          "completed":25
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9e60e4b0d636137ff024",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff024",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":16,
-          "inProgress":0,
-          "completed":24
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9e6be4b0d636137ff025",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff025",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":15,
-          "inProgress":0,
-          "completed":25
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ea4e4b0d636137ff026",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff026",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":16,
-          "inProgress":0,
-          "completed":24
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9eade4b0d636137ff027",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff027",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9eb5e4b0d636137ff028",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff028",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":13,
-          "inProgress":0,
-          "completed":27
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ebbe4b0d636137ff029",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff029",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ec2e4b0d636137ff02a",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff02a",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":15,
-          "inProgress":0,
-          "completed":25
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ecae4b0d636137ff02b",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff02b",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":13,
-          "inProgress":0,
-          "completed":27
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ed9e4b0d636137ff02c",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff02c",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":16,
-          "inProgress":0,
-          "completed":24
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ee1e4b0d636137ff02d",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff02d",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":16,
-          "inProgress":0,
-          "completed":24
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9eeae4b0d636137ff02e",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff02e",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":13,
-          "inProgress":0,
-          "completed":27
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9ef3e4b0d636137ff02f",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff02f",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":16,
-          "inProgress":0,
-          "completed":24
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9efde4b0d636137ff030",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff030",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9f05e4b0d636137ff031",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff031",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":12,
-          "inProgress":0,
-          "completed":28
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9f0ce4b0d636137ff032",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff032",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":16,
-          "inProgress":0,
-          "completed":24
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9f14e4b0d636137ff033",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff033",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":15,
-          "inProgress":0,
-          "completed":25
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9f2fe4b0d636137ff034",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff034",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":15,
-          "inProgress":0,
-          "completed":25
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"510e9f37e4b0d636137ff035",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"7ff035",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_regularTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "oxalis"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"5113621ce4b02448f8a1784d"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"normalTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136aaee4b02448f8a178af",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178af",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":13,
-          "inProgress":0,
-          "completed":27
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136ab7e4b02448f8a178b3",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178b3",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136abfe4b02448f8a178b7",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178b7",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":15,
-          "inProgress":0,
-          "completed":25
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136ac8e4b02448f8a178bb",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178bb",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136ad1e4b02448f8a178bf",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178bf",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":13,
-          "inProgress":0,
-          "completed":27
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136adae4b02448f8a178c3",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178c3",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136ae5e4b02448f8a178c7",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178c7",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      },
-      {
-        "id":"51136af1e4b02448f8a178cb",
-        "team":"Structure of Neocortical Circuits Group",
-        "formattedHash":"a178cb",
-        "seedIdHeidelberg":0,
-        "projectName":"tracingMethodsComparison",
-        "type":{
-          "summary":"methodComaprison_arbitraryTracing",
-          "description":"",
-          "expectedTime":{
-            "min":1,
-            "max":5,
-            "maxHard":10
-          },
-          "team":"Structure of Neocortical Circuits Group",
-          "settings":{
-            "allowedModes":[
-              "arbitrary"
-            ],
-            "branchPointsAllowed":false,
-            "somaClickingAllowed":true
-          },
-          "_id":{
-            "$oid":"51136235e4b02448f8a1784e"
-          }
-        },
-        "dataSet":"",
-        "editPosition":[
-          1,
-          1,
-          1
-        ],
-        "neededExperience":{
-          "domain":"arbitraryTracing",
-          "value":1
-        },
-        "priority":100,
-        "created":"2014-02-17 15:11",
-        "status":{
-          "open":14,
-          "inProgress":0,
-          "completed":26
-        },
-        "isTraining":false,
-        "training":null
-      }
-    ]


Villiany implementation for limiter

Villiany implementation for limiter

--- server/packages/limiter/index.coffee
+++ server/packages/limiter/index.coffee
@@ -1,5 +1,6 @@

 moment = require 'moment'
+Promise = require 'bluebird'

 audit = require 'audit'
 errors = require 'errors'
@@ -37,14 +38,28 @@
 						(isLimited) ->
 							return next() unless isLimited

-							instance.ttl(keys).then (ttl) ->
+							promise = if req.reportVilliany?

-								next errors.instantiate(
-									'limiterThreshold'
-									message
-									moment().add('seconds', ttl).fromNow()
+								req.reportVilliany(
+									endpoint.villianyScore ? 20
+									"rpc://#{route}"
 								)
+
+							else
+
+								Promise.resolve false

+							promise.then (isVillian) ->
+								return if isVillian
+
+								instance.ttl(keys).then (ttl) ->
+
+									next errors.instantiate(
+										'limiterThreshold'
+										message
+										moment().add('seconds', ttl).fromNow()
+									)
+
 						(error) -> next error

 					)


Remove old rules controller that is not erb

--- app/assets/javascripts/angular/controllers/rules_ctrl.js.coffee
+++ app/assets/javascripts/angular/controllers/rules_ctrl.js.coffee
@@ -1,4 +0,0 @@
-App.controller 'RulesCtrl', ['$scope', ($scope) ->
-  $scope.ruleTypes = () ->
-   ['INSTRUMENT_SURVEY_LIMIT_RULE']
-]


add status icon and email .list

add status icon and email .list

--- app/assets/javascripts/app/controllers/_channel/email.js.coffee
+++ app/assets/javascripts/app/controllers/_channel/email.js.coffee
@@ -225,7 +225,8 @@

   constructor: ->
     super
-    @interval(@load, 20000)
+    # @interval(@load, 20000)
+    @load()

   load: =>
     @ajax(


Client side Commit Req should not send paths with leading slashes

--- app/assets/javascripts/backbone/models/commit_request.js.coffee
+++ app/assets/javascripts/backbone/models/commit_request.js.coffee
@@ -83,12 +83,13 @@
   #
   mkdir: (path, dirname) =>
     console.log("mkdir: ", [path, dirname].join("/"))
+    path = if path.length == 0 then dirname else [path, dirname].join("/")
     request =
       {
         command: "mkdir",
         branch: gon.ref,
         commit_message: null,
-        path: [path, dirname].join("/")
+        path: path
       }
     @send(request)