mocks/jobs: added fail and error mock jobs

--- lib/mocks/jobs.coffee
+++ lib/mocks/jobs.coffee
@@ -1,23 +1,45 @@
 {EventEmitter}  = require 'events'

-module.exports =
-  MockJob: class MockJob extends EventEmitter
-    constructor: ->
-      super
-      @handle = 'job_handle'
-      @events = []
-    delayEmit: (event, timeout, args...) =>
-      @events.push {event, timeout, args}
-    start: =>
-      for {event, timeout, args} in @events
-        setTimeout @emit.bind(@), timeout, event, @handle, args...
-      @
-  CompleteJob: class CompleteJob extends MockJob
-    constructor: (timeout=500) ->
-      super
-      @delayEmit 'complete', timeout
-  DataJob: class DataJob extends CompleteJob
-    constructor: (data, timeout=500) ->
-      super timeout
-      data_interval = timeout / (data.length + 1)
-      @delayEmit 'data', (i + 1) * data_interval, el for el, i in data
+class MockJob extends EventEmitter
+  constructor: ->
+    super
+    @handle = 'job_handle'
+    @events = []
+  delayEmit: (event, timeout, args...) =>
+    @events.push {event, timeout, args}
+  start: =>
+    for {event, timeout, args} in @events
+      setTimeout @emit.bind(@), timeout, event, @handle, args...
+    @
+
+class FinishJob extends MockJob
+  constructor: (event, timeout = 500) ->
+    super
+    @delayEmit event, timeout
+
+class IntervalJob extends FinishJob
+  constructor: (finish_event, event, data, timeout = 500) ->
+    # Short timeouts can cause the finish event to fire before all the data
+    # events fire
+    timeout = if timeout <= data.length then (data.length + 1) * 2 else timeout
+    super finish_event, timeout
+    interval = timeout / (data.length + 1)
+    @delayEmit event, (i + 1) * interval, el for el, i in data
+
+class CompleteJob extends FinishJob
+  constructor: (timeout = 500) ->
+    super 'complete', timeout
+
+class DataJob extends IntervalJob
+  constructor: (data, timeout = 500) ->
+    super 'complete', 'data', data, timeout
+
+class FailJob extends FinishJob
+  constructor: (timeout = 500) ->
+    super 'fail', timeout
+
+class ErrorJob extends IntervalJob
+  constructor: (messages, timeout = 500) ->
+    super 'fail', 'warning', messages, timeout
+
+module.exports = {MockJob, CompleteJob, DataJob, FailJob, ErrorJob}


Added rejection on socket error `https://github.com/realtymaps/promise-ftp/issues/2`

--- lib/promiseFtp.coffee
+++ lib/promiseFtp.coffee
@@ -188,7 +188,16 @@

     # common promise, connection-check, and reconnect logic
     commonLogicFactory = (name, handler) ->
-      promisifiedClientMethods[name] = Promise.promisify(client[name], client)
+      promisifiedClientMethods[name] = (args...) -> new Promise (resolve, reject) ->
+        onError = (err) ->
+          reject(err)
+        client.once('error', onError)
+        client[name] args..., (err, res) ->
+          client.removeListener 'error', onError
+          if err
+            reject err
+          else
+            resolve res
       if !handler
         handler = promisifiedClientMethods[name]
       (args...) ->


Scan line tags manually to check if a position is a tag or is commented

--- lib/tag-finder.coffee
+++ lib/tag-finder.coffee
@@ -1,7 +1,8 @@
 {Range} = require 'atom'
 _ = require 'underscore-plus'
-SelectorCache = require './selector-cache'
 SelfClosingTags = require './self-closing-tags'
+TAG_SELECTOR_REGEX = /(\b|\.)(meta\.tag|punctuation\.definition\.tag)/
+COMMENT_SELECTOR_REGEX = /(\b|\.)comment/

 # Helper to find the matching start/end tag for the start/end tag under the
 # cursor in XML, HTML, etc. editors.
@@ -10,23 +11,40 @@
   constructor: (@editor) ->
     @tagPattern = /(<(\/?))([^\s>]+)([\s>]|$)/
     @wordRegex = /[^>\r\n]*/
-    @tagSelector = SelectorCache.get('meta.tag | punctuation.definition.tag')
-    @commentSelector = SelectorCache.get('comment.*')

   patternForTagName: (tagName) ->
     tagName = _.escapeRegExp(tagName)
     new RegExp("(<#{tagName}([\\s>]|$))|(</#{tagName}>)", 'gi')

   isRangeCommented: (range) ->
-    scopes = @editor.scopeDescriptorForBufferPosition(range.start).getScopesArray()
-    @commentSelector.matches(scopes)
+    @scopesForPositionMatchRegex(range.start, COMMENT_SELECTOR_REGEX)

   isTagRange: (range) ->
-    scopes = @editor.scopeDescriptorForBufferPosition(range.start).getScopesArray()
-    @tagSelector.matches(scopes)
+    @scopesForPositionMatchRegex(range.start, TAG_SELECTOR_REGEX)

   isCursorOnTag: ->
-    @tagSelector.matches(@editor.getLastCursor().getScopeDescriptor().getScopesArray())
+    @scopesForPositionMatchRegex(@editor.getCursorBufferPosition(), TAG_SELECTOR_REGEX)
+
+  scopesForPositionMatchRegex: (position, regex) ->
+    {tokenizedBuffer, buffer} = @editor
+    column = 0
+    lineLength = buffer.lineLengthForRow(position.row)
+    line = tokenizedBuffer.tokenizedLineForRow(position.row)
+    scopeIds = line.openScopes.slice()
+    for tag in line.tags by 1
+      if tag >= 0
+        nextColumn = column + tag
+        break if nextColumn > position.column or nextColumn is lineLength
+        column = nextColumn
+      else if (tag & 1) is 1
+        scopeIds.push(tag)
+      else
+        scopeIds.pop()
+
+    for scopeId in scopeIds by 1
+      scope = tokenizedBuffer.grammar.scopeForId(scopeId)
+      return true if regex.test(scope)
+    false

   findStartTag: (tagName, endPosition) ->
     scanRange = new Range([0, 0], endPosition)


Use 'reloaded' event on Theme Manager to update themes.

--- lib/ui-watcher.coffee
+++ lib/ui-watcher.coffee
@@ -17,13 +17,12 @@
     @watchForPackageChanges()

   watchForPackageChanges: ->
-    atom.config.observe 'core.themes', (themeNames) =>
+    atom.themes.on 'reloaded', =>
       # we need to destroy all watchers as all theme packages are destroyed when a
       # theme changes.
       watcher.destroy() for name, watcher of @watchedThemes

       @watchedThemes = {}
-
       # Rewatch everything!
       @watchTheme(theme) for theme in atom.themes.getActiveThemes()


Add debug state param

Add debug state param

--- Net_action.coffee
+++ Net_action.coffee
@@ -1,11 +1,12 @@
 request = require 'request'

 DEFAULT_FORMAT = 'json'
-DEBUG_STATE = true

 module.exports = class Net_action

-	constructor: (@ROOT_DATA) ->
+	constructor: (@ROOT_DATA, @DEBUG_STATE) ->
+		unless @DEBUG_STATE
+			@DEBUG_STATE = false

 	get: ({ressource, params, @format, successCallback, errorCallback}) ->
 		unless @format?
@@ -53,7 +54,7 @@

 	_interact: ({method, ressource, params, scb, ecb}) ->
 		unless @ROOT_DATA?
-			if DEBUG_STATE
+			if @DEBUG_STATE
 				console.error '#[!] No host defined !!'
 			return false

@@ -70,7 +71,7 @@
 		else
 			url = "#{ressource}"

-		if DEBUG_STATE
+		if @DEBUG_STATE
 			console.log "#[+] EXEC #{method} -> #{@ROOT_DATA}/#{url}"

 		request
@@ -79,7 +80,7 @@
 			form: params
 			uri: "#{@ROOT_DATA}/#{url}"
 			(error, response, result) =>
-				if result?
+				if result? and @format is DEFAULT_FORMAT
 					if result.State? and result.State
 						scb result
 					else


Making `process.execPath` point to `coffee` when running .coffee files

Related: #1303 set `process.argv[0]` to `coffee`. This makes
`process.execPath` consistent with that change.

--- command.coffee
+++ command.coffee
@@ -53,7 +53,7 @@
 # Run `coffee` by parsing passed options and determining what action to take.
 # Many flags cause us to divert before compiling anything. Flags passed after
 # `--` will be passed verbatim to your script as arguments in `process.argv`
-exports.run = ->
+exports.run = (coffeePath) ->
   parseOptions()
   return forkNode()                      if opts.nodejs
   return usage()                         if opts.help
@@ -67,6 +67,7 @@
     opts.literals = sources.splice(1).concat opts.literals
   process.ARGV = process.argv = process.argv.slice(0, 2).concat opts.literals
   process.argv[0] = 'coffee'
+  process.execPath = coffeePath
   compileScripts()

 # Asynchronously read in each CoffeeScript in a list of source files and


Using string interpolation when adding extension

--- command.coffee
+++ command.coffee
@@ -79,7 +79,7 @@
     compile = (source, sourceIndex, topLevel) ->
       path.exists source, (exists) ->
         if topLevel and not exists and source[-7..] isnt '.coffee'
-            return compile source + ".coffee", sourceIndex, topLevel
+            return compile "#{source}.coffee", sourceIndex, topLevel

         throw new Error "File not found: #{source}" if topLevel and not exists
         fs.stat source, (err, stats) ->


Removed some more unnecessary comments.

Removed some more unnecessary comments.

--- examples/delaunay.coffee
+++ examples/delaunay.coffee
@@ -64,9 +64,6 @@
 # The function `circumCircleCenter` computes the center of the circum-circle
 # of a given triangle, specified by three input points.
 circumCircleCenter = (a, b, c) ->
-
-  # The lifted normal scaled to z=-1/2 and projected back onto the x,y-plane
-  # yields the desired point.
   n = liftedNormal a, b, c
   unlift n.times -0.5 / n.z if Math.abs(n.z) > 1e-6

@@ -77,11 +74,6 @@
 # outside or on the circle through points a, b and c. A positive return value
 # means inside, zero means on and a negative value means outside.
 inclusionInCircumCircle = (a, b, c, d) ->
-
-  # Equivalently, we can ask whether the lift of d is below, on or above the
-  # plane formed by the lifts of the points a, b and c, which we can readily
-  # read of the dot product of the lifted normal and the vector from the lift
-  # of a to the lift of d.
   liftedNormal(a, b, c).dot lift(d).minus lift(a)

@@ -120,10 +112,6 @@
     # triangle in this triangulation, if any, which contains the two or three
     # given vertices in the correct order.
     find: (a, b, c) ->
-      # If three vertices are given, we look for all three possible vertex
-      # orders with the same orientation in the triangle list.  Otherwise, we
-      # look for the corresponding third vertex, if any, and call find
-      # recursively.
      if c?
         seq(seq(a, b, c), seq(b, c, a), seq(c, a, b)).
           find((t) => @triangles__.contains(t))
@@ -240,10 +228,8 @@
     # The method `plus` creates a new Delaunay triangulation with the given
     # `Point2d` instance added as a site.
     plus: (p) ->
-      # We return the current instance unchanged if the site is already in.
       if @sites__.contains p
         this
-      # Otherwise, there's work to do...
       else
         # ...


Elegant ME

Elegant ME

--- mail/sendmaild.coffee
+++ mail/sendmaild.coffee
@@ -31,7 +31,7 @@
     currentMail = mail
     mailSender.sendMailPromised(
       to: mail.to
-      from: "Saaby<#{config.mail.auth.mailaddr}>"
+      from: "ElegantSZM<#{config.mail.auth.mailaddr}>"
       subject: mail.title
       html : require('./sender').replace(mail.html)
     )


account/shortcuts: change instructions text since ux is changed

--- client/account/lib/views/accounteditshortcuts.coffee
+++ client/account/lib/views/accounteditshortcuts.coffee
@@ -9,7 +9,7 @@
 class AccountEditShortcuts extends kd.View

   INSTRUCTIONS_CSS_CLASS = 'instructions'
-  INSTRUCTIONS_PARTIAL = 'To change a shortcut, click the key combination, then type the new keys.'
+  INSTRUCTIONS_PARTIAL = 'To change a shortcut, click on it, then type the new keys.'
   RESTORE_BUTTON_TITLE = 'Restore Defaults'
   RESTORE_BUTTON_CLASS_NAME = 'solid light-gray medium restore'
   RESTORE_CONFIRM_TEXT = 'Are you sure you want to restore the default shortcuts?'


MachineSettingsModal: Removed dummy line.

--- client/app/lib/providers/machinesettingsmodal.coffee
+++ client/app/lib/providers/machinesettingsmodal.coffee
@@ -46,8 +46,6 @@

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

-    window.ali = this
-
     options.cssClass = 'machine-settings-modal AppModal'
     options.title    = 'VM Settings'
     options.width    = 805


utils: gravatar url getter added

utils: gravatar url getter added

--- client/landing/site.landing/coffee/core/utils.coffee
+++ client/landing/site.landing/coffee/core/utils.coffee
@@ -315,6 +315,13 @@
       error       : callbacks.error

+  getGravatarUrl : (size = 80, hash) ->
+
+    fallback = "https://koding-cdn.s3.amazonaws.com/square-avatars/default.avatar.#{size}.png"
+
+    return "//gravatar.com/avatar/#{hash}?size=#{size}&d=#{fallback}&r=g"
+
+
   getGroupLogo : ->

     { group } = KD.config


[skip] Unselected selected conversations when giving input focus to the search box (2m)

--- app/assets/javascripts/houston/feedback/views/conversations_view.coffee
+++ app/assets/javascripts/houston/feedback/views/conversations_view.coffee
@@ -35,6 +35,7 @@
     'mouseup .feedback-search-result': 'resultReleased'
     'keydown': 'keydown'
     'keydown #q': 'keydownSearch'
+    'focus #q': 'onFocusSearch'
     'click .feedback-conversation-close': 'selectNone'
     'click .feedback-conversation-copy-url': 'copyUrl'
     'click .feedback-remove-tag': 'removeTag'
@@ -263,6 +264,9 @@
       e.stopImmediatePropagation()
       @selectFirstResult()

+  onFocusSearch: ->
+    @selectNone()
+
   selectFirstResult: ->
     @select @$el.find('.feedback-search-result:first'), 'new'


Renamed some stuff

Renamed some stuff

--- core/app/backbone/views/react_feed_activities.coffee
+++ core/app/backbone/views/react_feed_activities.coffee
@@ -26,15 +26,22 @@
     $(window).off "scroll", @checkScrolledPosition

   render: ->
-    _div [id:"feed_activity_list"],
+    _div [],
       @model().map (model) =>
-        switch model.get("action")
-          when "created_comment"
-            ReactCreatedCommentActivity(model: model)
-          when "created_sub_comment"
-            ReactCreatedSubCommentActivity(model: model)
-          when "followed_user"
-            ReactFollowedUserActivity(model: model)
+        ReactActivity model: model
+
+ReactActivity = React.createBackboneClass
+  displayName: 'ReactActivity'
+
+  render: ->
+    switch @model().get("action")
+      when "created_comment"
+        ReactCreatedCommentActivity model: @model()
+      when "created_sub_comment"
+        ReactCreatedSubCommentActivity model: @model()
+      when "followed_user"
+        ReactFollowedUserActivity model: @model()
+

 ReactCreatedCommentActivity = React.createBackboneClass
   displayName: 'ReactCreatedCommentActivity'
@@ -44,7 +51,7 @@
     fact = new Fact @model().get('fact')
     comment = new Comment @model().get('comment')

-    ReactActivity {
+    ReactGenericActivity {
         model: user
         time: @model().get('created_at')
         href: fact.get('proxy_open_url')
@@ -66,7 +73,7 @@
     comment = new Comment @model().get('comment')
     sub_comment = new Comment @model().get('sub_comment')

-    ReactActivity {
+    ReactGenericActivity {
         model: user
         time: @model().get('created_at')
         href: fact.get('proxy_open_url')
@@ -92,7 +99,7 @@
     user = new User @model().get('user')
     followed_user = new User @model().get('followed_user')

-    ReactActivity {
+    ReactGenericActivity {
         model: user,
         time: @model().get('created_at')
         href: followed_user.link()
@@ -107,7 +114,7 @@
           ]
       }

-ReactActivity = React.createBackboneClass
+ReactGenericActivity = React.createBackboneClass
   render: ->
     user = @model()


Fix runaway issues with certain escape sequences

Certain Roff sequences see the next character as an arbitrary delimiter,
which drastically elevates the potential for incorrect highlighting:

    "\labc" … # Continues highlighting until it meets an "a"

These sequences are unlikely to be used inside Pic strings; highlighting
them offers no benefit to the reader, either.

--- grammars/pic.cson
+++ grammars/pic.cson
@@ -443,7 +443,10 @@
 		end:   '"'
 		beginCaptures: 0: name: "punctuation.definition.string.begin.pic"
 		endCaptures:   0: name: "punctuation.definition.string.end.pic"
-		patterns: [include: "text.roff#escapes"]
+		patterns: [
+			{match: "\\\\(?:[bCDhHlLNoSvwxX]|s[^\\d\\-+])"}
+			{include: "text.roff#escapes"}
+		]

 	# Lines which delimit regions of preprocessor source


Always have correct option id

Always have correct option id

--- angular/core/components/poll/count/vote_form/poll_count_vote_form.coffee
+++ angular/core/components/poll/count/vote_form/poll_count_vote_form.coffee
@@ -6,8 +6,7 @@
       prepareFn: (optionName) ->
         option = PollService.optionByName($scope.stance.poll(), optionName)
         $scope.$emit 'processing'
-        pollOptionId = if option.name then option.id else $scope.yes.id
-        $scope.stance.stanceChoicesAttributes = [poll_option_id: pollOptionId]
+        $scope.stance.stanceChoicesAttributes = [poll_option_id: option.id]

     $scope.yesColor = AppConfig.pollColors.count[0]
     $scope.noColor  = AppConfig.pollColors.count[1]


Hide inbox list

Hide inbox list

--- app/controllers/lists.coffee
+++ app/controllers/lists.coffee
@@ -47,6 +47,7 @@
       @input.val ""

   addOne: (list) =>
+    return if list.id is "inbox"
     listItem = new ListItem( list: list )
     @lists.append listItem.render().el


Fetch AppStorage before refreshApps

Fetch AppStorage before refreshApps

--- client/landing/app/Applications/StartTab.kdapplication/AppView.coffee
+++ client/landing/app/Applications/StartTab.kdapplication/AppView.coffee
@@ -12,7 +12,8 @@
     mainView       = @getSingleton('mainView')
     appsController = @getSingleton("kodingAppsController")
     appsController.on "AppsRefreshed", (apps)=>
-      @decorateApps apps
+      @getSingleton("kodingAppsController").appStorage.fetchStorage (storage)=>
+        @decorateApps apps

     # mainView.sidebar.finderResizeHandle.on "DragInAction", =>
     #   log "DragInAction", mainView.contentPanel.getWidth()


server/invitetoteambycsv: add result argument to callback

--- servers/lib/server/handlers/invitetoteambycsv.coffee
+++ servers/lib/server/handlers/invitetoteambycsv.coffee
@@ -34,19 +34,19 @@
       file.pipe(fs.createWriteStream(fileName))

     busboy.on 'finish', ->
-      processInvitations fileName, client, (err) ->
+      processInvitations fileName, client, (err, result) ->
         return respond 500, err if err

-        respond 200, "That's all folks!"
+        respond 200, result

     return req.pipe busboy

 processInvitations = (fileName, client, callback) ->
   fs.readFile fileName, 'utf8', (err, content) ->
-    return callback err if err
+    return callback err, null if err

     parser content.toString('utf8'), csvParseOpts, (err, data) ->
-      return callback err if err
+      return callback err, null if err

       { JInvitation } = (require './../bongo').models
       JInvitation.create client, { invitations: data }, callback


Log number of retries

Log number of retries

--- services/track-changes/app/coffee/DiffManager.coffee
+++ services/track-changes/app/coffee/DiffManager.coffee
@@ -43,7 +43,7 @@
 		callback = (error, args...) ->
 			if error?
 				if error.retry and retries > 0
-					logger.warn {error, project_id, doc_id, version}, "retrying getDocumentBeforeVersion"
+					logger.warn {error, project_id, doc_id, version, retries}, "retrying getDocumentBeforeVersion"
 					retry()
 				else
 					_callback(error)


deduplicate question types constant data

--- jsapp/xlform/src/view.icons.coffee
+++ jsapp/xlform/src/view.icons.coffee
@@ -1,137 +1,49 @@
 _ = require 'underscore'
 Backbone = require 'backbone'
+constants = require '../../js/constants'

 module.exports = do ->
   _t = require("utils").t

-  iconDetails = [
-    # row 1
-      label: _t("Select One")
-      faClass: "dot-circle-o"
-      grouping: "r1"
-      id: "select_one"
-    ,
-      label: _t("Select Many")
-      faClass: "list-ul"
-      grouping: "r1"
-      id: "select_multiple"
-    ,
-      label: _t("Text")
-      faClass: "lato-text"
-      grouping: "r1"
-      id: "text"
-    ,
-      label: _t("Number")
-      faClass: "lato-integer"
-      grouping: "r1"
-      id: "integer"
-    ,
+  addIconToRow = (typeDef, group) =>
+    iconDetails.push({
+      label: typeDef.label,
+      faClass: typeDef.faIcon.replace("fa-", ""),
+      grouping: group,
+      id: typeDef.id
+    })
+    return

-    # row 2
-      label: _t("Decimal")
-      faClass: "lato-decimal"
-      grouping: "r2"
-      id: "decimal"
-    ,
-      label: _t("Date")
-      faClass: "calendar"
-      grouping: "r2"
-      id: "date"
-    ,
-      label: _t("Time")
-      faClass: "clock-o"
-      grouping: "r2"
-      id: "time"
-    ,
-      label: _t("Date & time")
-      faClass: "calendar clock-over"
-      grouping: "r2"
-      id: "datetime"
-    ,
-
-    # r3
-      label: _t("Point")
-      faClass: "map-marker"
-      grouping: "r3"
-      id: "geopoint"
-    ,
-      label: _t("Photo")
-      faClass: "picture-o"
-      grouping: "r3"
-      id: "image"
-    ,
-      label: _t("Audio")
-      faClass: "volume-up"
-      grouping: "r3"
-      id: "audio"
-    ,
-      label: _t("Video")
-      faClass: "video-camera"
-      grouping: "r3"
-      id: "video"
-    ,
-
-    # r4
-      label: _t("Line")
-      faClass: "share-alt"
-      grouping: "r4"
-      id: "geotrace"
-    ,
-      label: _t("Note")
-      faClass: "bars"
-      grouping: "r4"
-      id: "note"
-    ,
-      label: _t("Barcode / QR Code")
-      faClass: "qrcode"
-      grouping: "r4"
-      id: "barcode"
-    ,
-      label: _t("Acknowledge")
-      faClass: "check-square-o"
-      grouping: "r4"
-      id: "acknowledge"
-    ,
-
-    # r5
-      label: _t("Area")
-      faClass: "square"
-      grouping: "r5"
-      id: "geoshape"
-    ,
-      label: _t("Rating")
-      faClass: "server"
-      grouping: "r5"
-      id: "score"
-    ,
-      label: _t("Question Matrix")
-      faClass: "table"
-      grouping: "r5"
-      id: "kobomatrix"
-    ,
-      label: _t("Ranking")
-      faClass: "sort-amount-desc"
-      grouping: "r5"
-      id: "rank"
-    ,
-
-    # r6
-      label: _t("Calculate")
-      faClass: "lato-calculate"
-      grouping: "r6"
-      id: "calculate"
-    ,
-      label: _t("File")
-      faClass: "file"
-      grouping: "r6"
-      id: "file"
-    ,
-      label: _t("Range")
-      faClass: "lato-range"
-      grouping: "r6"
-      id: "range"
-    ,
-    ]
+  iconDetails = []
+  # row 1
+  addIconToRow(constants.QUESTION_TYPES.get("select_one"),  "r1")
+  addIconToRow(constants.QUESTION_TYPES.get("select_multiple"), "r1")
+  addIconToRow(constants.QUESTION_TYPES.get("text"), "r1")
+  addIconToRow(constants.QUESTION_TYPES.get("integer"), "r1")
+  # row 2
+  addIconToRow(constants.QUESTION_TYPES.get("decimal"), "r2")
+  addIconToRow(constants.QUESTION_TYPES.get("date"), "r2")
+  addIconToRow(constants.QUESTION_TYPES.get("time"), "r2")
+  addIconToRow(constants.QUESTION_TYPES.get("datetime"), "r2")
+  # row 3
+  addIconToRow(constants.QUESTION_TYPES.get("geopoint"), "r3")
+  addIconToRow(constants.QUESTION_TYPES.get("image"), "r3")
+  addIconToRow(constants.QUESTION_TYPES.get("audio"), "r3")
+  addIconToRow(constants.QUESTION_TYPES.get("video"), "r3")
+  # row 4
+  addIconToRow(constants.QUESTION_TYPES.get("geotrace"), "r4")
+  addIconToRow(constants.QUESTION_TYPES.get("note"), "r4")
+  addIconToRow(constants.QUESTION_TYPES.get("barcode"), "r4")
+  addIconToRow(constants.QUESTION_TYPES.get("acknowledge"), "r4")
+  # row 5
+  addIconToRow(constants.QUESTION_TYPES.get("geoshape"), "r5")
+  addIconToRow(constants.QUESTION_TYPES.get("score"), "r5")
+  addIconToRow(constants.QUESTION_TYPES.get("kobomatrix"), "r5")
+  addIconToRow(constants.QUESTION_TYPES.get("rank"), "r5")
+  # row 6
+  addIconToRow(constants.QUESTION_TYPES.get("calculate"), "r6")
+  addIconToRow(constants.QUESTION_TYPES.get("file"), "r6")
+  addIconToRow(constants.QUESTION_TYPES.get("range"), "r6")

   class QtypeIcon extends Backbone.Model
     defaults:


Do not track anonymous sessions

Do not track anonymous sessions

And DRY the controller a bit.

--- services/web/app/coffee/Features/Analytics/AnalyticsController.coffee
+++ services/web/app/coffee/Features/Analytics/AnalyticsController.coffee
@@ -4,25 +4,25 @@

 module.exports = AnalyticsController =
 	updateEditingSession: (req, res, next) ->
-		userId    = AuthenticationController.getLoggedInUserId(req) or req.sessionID
+		userId    = AuthenticationController.getLoggedInUserId(req)
 		projectId = req.params.projectId

-		AnalyticsManager.updateEditingSession userId, projectId, {}, (error) ->
-			if error instanceof Errors.ServiceNotConfiguredError
-				# ignore, no-op
-				return res.send(204)
-			else if error?
-				return next(error)
-			else
-				return res.send 204
+		if userId?
+			AnalyticsManager.updateEditingSession userId, projectId, {}, (error) ->
+				respondWith(error, res, next)
+		else
+			res.send 204

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


copy all .css from native-styleS

copy all .css from native-styleS

--- tasks/fresh/modules/steroids-module-copy-default-native-styles.coffee
+++ tasks/fresh/modules/steroids-module-copy-default-native-styles.coffee
@@ -9,7 +9,7 @@
       native:
         expand: true
         cwd: "app/common/native-styles/"
-        src: "default.css"
+        src: "*.css"
         dest: "dist/native-styles"
         ext: ".css"
   }


Remove reference to window in cql patient JS

--- app/assets/javascripts/cqlpatient.js.coffee
+++ app/assets/javascripts/cqlpatient.js.coffee
@@ -57,7 +57,7 @@
             classname = CQL_QDM.OIDMap.oidToClassName(dc)
           unless datatypes[classname]?
             datatypes[classname] = []
-          cql_dc = new window['CQL_QDM'][classname](dc)
+          cql_dc = new CQL_QDM[classname](dc)
           cql_dc['bonnie_type'] = type
           datatypes[classname].push cql_dc
     datatypes


Keg JS common fix

Keg JS common fix

--- app/assets/javascripts/keg_common.js.coffee
+++ app/assets/javascripts/keg_common.js.coffee
@@ -4,51 +4,51 @@

 fixHelper = (e, ui) ->
   ui.children().each ->
-    $(this).width $(this).width()
-    $(this).children().each ->
-      $(this).width $(this).width()
+    $(@).width $(@).width()
+    $(@).children().each ->
+      $(@).width $(@).width()
   $(ui).closest("table").find("th").each ->
-    $(this).width $(this).width()
+    $(@).width $(@).width()
   ui

 $.fn.bind_sortable = ->
-  $(this).sortable
+  $(@).sortable
     helper: fixHelper
     update: (event, ui) ->
       $.ajax
         type: "POST"
-        data: $(this).sortable("serialize", { key: $(this).data("sortable-key")})
-        url: $(this).data("sortable-url")
-      $(this).parent().effect "highlight", {}, 2000
+        data: $(@).sortable("serialize", { key: $(@).data("sortable-key")})
+        url: $(@).data("sortable-url")
+      $(@).parent().effect "highlight", {}, 2000

 $.fn.convert_remote_links = ->
   $("[remote-links]").find("a").each ->
-    $(this).attr("data-remote", "true") unless $(this).attr("href") is "#"
+    $(@).attr("data-remote", "true") unless $(@).attr("href") is "#"

 $.fn.bind_modal_data_url = ->
   $("[data-url]").each ->
-    $(this).load_modal_data_url()
+    $(@).load_modal_data_url()

 $.fn.load_modal_data_url = ->
-  $(this).bind "click", ->
-    el_id = "#" + $(this).data("controls-modal") + " .in_body"
+  $(@).bind "click", ->
+    el_id = "#" + $(@).data("controls-modal") + " .in_body"
     $(el_id).html ""
     $.ajax
-      url: $(this).data("url")
+      url: $(@).data("url")
       complete: (jqXHR) ->
         $(el_id).spin false
         $(el_id).html jqXHR.responseText

 $.fn.concat_checkbox_text = ->
   $str = ""
-  $(this).find("input[type='checkbox']:checked").each ->
-    $str +=  "" + $(this).parent().text() + " "
+  $(@).find("input[type='checkbox']:checked").each ->
+    $str +=  "" + $(@).parent().text() + " "
   $str

 $.fn.bind_collapsible_label = ->
-  $switch = $($(this).data("collapsible-label"))
-  $main_el = $($(this).data("collapsible-main"))
-  $opt_el = $($(this).data("collapsible-opt"))
+  $switch = $($(@).data("collapsible-label"))
+  $main_el = $($(@).data("collapsible-main"))
+  $opt_el = $($(@).data("collapsible-opt"))

   $switch.addClass("switch")
   $main_el.hide()
@@ -56,8 +56,8 @@

   $switch.on
     click: ->
-      $(this).toggleClass("open")
-      if $(this).hasClass("open")
+      $(@).toggleClass("open")
+      if $(@).hasClass("open")
         $main_el.show()
         $opt_el.hide()
       else
@@ -65,8 +65,8 @@
         $opt_el.show()

 $.fn.bind_checkboxes_clone = ->
-  $el = $($(this).data("checkboxes-clone"))
-  $new_id = $(this).data("checkboxes-clone-into")
+  $el = $($(@).data("checkboxes-clone"))
+  $new_id = $(@).data("checkboxes-clone-into")

   $str = $el.concat_checkbox_text()
   $new_el = $("

").hide()
@@ -80,17 +80,17 @@
       $new_el.html($str)

 $.fn.bind_boolean_value = ->
-  $(this).on
+  $(@).on
     click: ->
-      $(this).parent().find("a").removeClass("active")
-      $hidden = $(this).parent().next("input[type='hidden']")
-
-      $val = $(this).data("boolean-value")
+      $(@).parent().find("a").removeClass("active")
+      $hidden = $(@).parent().next("input[type='hidden']")
+
+      $val = $(@).data("boolean-value")
       $hid_val = $hidden.val()

       if ("#{$val}" != "#{$hid_val}")
         $hidden.val($val)
-        $(this).addClass("active")
+        $(@).addClass("active")
       else
         $hidden.val("")

@@ -98,46 +98,50 @@

 $.fn.bind_switches = ->
   $(".switch").each ->
-    $(this).bind "click", ->
-      el = $("#" + $(this).data("switchable"))
-      if $(this).hasClass("open")
-        $(this).removeClass "open"
-        $(this).addClass "closed"
+    $(@).bind "click", ->
+      el = $("#" + $(@).data("switchable"))
+      if $(@).hasClass("open")
+        $(@).removeClass "open"
+        $(@).addClass "closed"
         el.hide()
       else
-        $(this).removeClass "closed"
-        $(this).addClass "open"
+        $(@).removeClass "closed"
+        $(@).addClass "open"
         el.show()

 bind_clearable_fields = ->
   $("[data-clearable-field]").each ->
-    input = $(this)
-    form = (if input.length > 0 then $(input[0].form) else $())
-    link = $("")
-    $(this).after link
-    input.on
+    $input = $(@)
+    # $form = (if $input.length > 0 then $($input[0].form) else $())
+    $form = $input.parent("form")
+    $link = $("")
+    $(@).after $link
+
+    $input.on
       change: ->
-        form.submit()
-      changeDate: ->
-        form.submit()
-
-    link.on
+        console.log "change", $input
+        $form.submit()
+      # changeDate: ->
+      #   console.log "changeDate", $input
+      #   $form.submit()
+
+    $link.on
       click: ->
-        input.val ""
-        form.submit()
+        $input.val ""
+        $form.submit()

 bind_filter_html_elements = ->
   $("[data-filter-html]").on "keyUp", ->
-    q = $(this).val()
-    src_tag = $(this).data("src-tag")
-    dest_tag = $(this).data("dest-tag")
-    src_class = $(this).data("src-class")
+    q = $(@).val()
+    src_tag = $(@).data("src-tag")
+    dest_tag = $(@).data("dest-tag")
+    src_class = $(@).data("src-class")

     reg = new RegExp(".*" + q, "i")
     els = $("#{src_tag}.#{src_class}")
     els.each ->
-      str = $(this).html()
-      id = "#" + $(this).attr("id").replace(src_tag + "_", dest_tag + "_")
+      str = $(@).html()
+      id = "#" + $(@).attr("id").replace(src_tag + "_", dest_tag + "_")
       unless q is ""
         if str.match(reg)
           $(id).show()
@@ -148,7 +152,7 @@

 bind_button_urls = ->
   $("[data-button-url]").on "click", ->
-    window.location = $(this).data("button-url")
+    window.location = $(@).data("button-url")
     false

 bind_datepicker = ->
@@ -157,7 +161,7 @@
     weekStart: 1

 $.fn.bind_counter = ->
-  $data = $(this).data()
+  $data = $(@).data()
   if $data
     $data.timerEnd = ->
       if $data.timerend
@@ -171,7 +175,7 @@
     $data.digitWidth = $data.digitwidth
     $data.digitHeight = $data.digitheight

-    $(this).countdown($data)
+    $(@).countdown($data)

 $.fn.remove_fields = (link) ->
   $(link).prev("input[type=hidden]").val "1"
@@ -220,32 +224,32 @@
   $(".form-vertical").removeClass("form-horizontal")

   $("[data-nicedit]").each ->
-    new nicEditor().panelInstance($(this).attr("id"))
+    new nicEditor().panelInstance($(@).attr("id"))

   $("[data-checkboxes-clone]").each ->
-    $(this).bind_checkboxes_clone()
+    $(@).bind_checkboxes_clone()
   $("[data-collapsible-label]").each ->
-    $(this).bind_collapsible_label()
+    $(@).bind_collapsible_label()

   $("[data-boolean-value]").each ->
-    $(this).bind_boolean_value()
+    $(@).bind_boolean_value()

   $("[data-active-select]").each ->
-    $url = $(this).data("active-select")
-    $(this).on
+    $url = $(@).data("active-select")
+    $(@).on
       change: ->
-        $to_url = $url.replace /__template__/, $(this).val()
+        $to_url = $url.replace /__template__/, $(@).val()
         window.location = $to_url

   $("[data-token-input]").each ->
-    $(this).tokenInput $(this).data("token-input"),
+    $(@).tokenInput $(@).data("token-input"),
       theme: "facebook"
-      prePopulate: $(this).data("token-pre")
+      prePopulate: $(@).data("token-pre")
       preventDuplicates: true
       crossDomain: false
-      hintText: $(this).data("token-hint-text")
-      noResultsText: $(this).data("token-no-results-text")
-      searchingText: $(this).data("token-searching-text")
+      hintText: $(@).data("token-hint-text")
+      noResultsText: $(@).data("token-no-results-text")
+      searchingText: $(@).data("token-searching-text")

   $("#flash_panel").delay(3000).fadeOut 3000


added id in conf form

added id in conf form

--- app/assets/javascripts/notebook/flow.coffee
+++ app/assets/javascripts/notebook/flow.coffee
@@ -99,6 +99,8 @@
         cell = cellView.model
         form.cell = cell
         conf.html("")
+
+        conf.append("
"+cell.id+"
")

         #in ports
         fsi = $("<fieldset></fieldset>")


Fix bug #851: Error when press Enter key when edit a wiki before closing the assignation lightbox pressing ESC key

--- app/coffee/modules/common/lightboxes.coffee
+++ app/coffee/modules/common/lightboxes.coffee
@@ -41,6 +41,7 @@
     close: ($el) ->
         docEl = angular.element(document)
         docEl.off(".lightbox")
+        docEl.off(".keyboard-navigation") # Hack: to fix problems in the WYSIWYG textareas when press ENTER

         $el.one "transitionend", =>
             $el.css('display', 'none')
@@ -92,6 +93,7 @@

 module.service("lightboxKeyboardNavigationService", LightboxKeyboardNavigationService)

+
 #############################################################################
 ## Generic Lighthbox Directive
 #############################################################################


Do the same for folders

Do the same for folders

--- lib/layervault/nodes/folder.coffee
+++ lib/layervault/nodes/folder.coffee
@@ -5,4 +5,5 @@
   create: (cb) -> @api.post(@path, {}, cb.bind(@))
   delete: (cb) -> @api.delete(@path, {}, cb.bind(@))
   move: (to, cb) -> @api.post("#{@path}/move", { to: to }, cb.bind(@))
+  rename: @move
   color: (color, cb) -> @api.put("#{@path}/color", { color: color }, cb.bind(@))


done -> then

done -> then

should close #74, but I can't reproduce the error.

--- lib/viewers/atom-pdf-viewer.coffee
+++ lib/viewers/atom-pdf-viewer.coffee
@@ -29,7 +29,7 @@
       split: 'right',
       activatePane: not opts.keepFocus
       searchAllPanes: true
-    ).done callback
+    ).then callback

   forwardSync: (pdfFile, texFile, line, col, opts = {}) ->
     view = _getActivePaneItem pdfFile


Client: Activity: Added likes tooltip to ActivityLikeLink

--- client/activity/lib/components/chatlistitem/activitylikelink.coffee
+++ client/activity/lib/components/chatlistitem/activitylikelink.coffee
@@ -1,6 +1,8 @@
 React        = require 'kd-react'
 classnames   = require 'classnames'
 ActivityFlux = require 'activity/flux'
+Tooltip      = require 'app/components/tooltip'
+ProfileText  = require 'app/components/profile/profiletext'

 module.exports = class ActivityLikeLink extends React.Component
@@ -25,9 +27,33 @@
       likeMessage @props.messageId

+  renderTooltipItems: (participant) ->
+
+    { actorsPreview } = @props.interactions.like
+
+    for participant of actorsPreview
+
+      if actorsPreview[participant]
+
+        <ProfileText account={actorsPreview[participant]} />
+
+
+  renderTooltip: ->
+
+    { actorsCount } = @props.interactions.like
+
+    return null  unless actorsCount
+
+    <Tooltip>
+      {@renderTooltipItems()}
+    </Tooltip>
+
+
   render: ->

-
+
+      {@renderTooltip()}
+


edited admin/shipping_methods.js to be more explicit when manipulating checkbox inputs so that additional checkboxes are not affected

Fixes #2465

--- core/app/assets/javascripts/admin/shipping_methods.js.coffee
+++ core/app/assets/javascripts/admin/shipping_methods.js.coffee
@@ -1,5 +1,5 @@
 $ ->
-  ($ 'input[type=checkbox]:not(:checked)').attr 'disabled', true  if ($ '.categories input:checked').length > 0
+  ($ 'fieldset.categories input[type=checkbox]:not(:checked)').attr 'disabled', true  if ($ '.categories input:checked').length > 0
   categoryCheckboxes = '.categories input[type=checkbox]'
   $(categoryCheckboxes).change ->
     if ($ this).is(':checked')


Send clonables always as list.

Send clonables always as list.

--- core/htdocs_source/src/pods/oxisection-form/component.coffee
+++ core/htdocs_source/src/pods/oxisection-form/component.coffee
@@ -97,7 +97,7 @@

             for name in names
                 clones = (f for f in fields when f.name is name)
-                if clones.length > 1
+                if clones[0].clonable
                     data[name] = (c.value for c in clones)
                 else
                     data[name] = clones[0].value


Sanitize content for triple mustaches.

Sanitize content for triple mustaches.

--- core/htdocs_source/src/pods/oxivalue-format/component.coffee
+++ core/htdocs_source/src/pods/oxivalue-format/component.coffee
@@ -1,6 +1,16 @@
 `import $ from "vendor/jquery"`
 `import Em from "vendor/ember"`
 `import moment from "vendor/moment"`
+
+jQuery.extend jQuery.expr[':'],
+    cleanup: (el) ->
+        ret = false
+        names = (attr.nodeName for attr in el.attributes \
+                    when /^on/.test(attr.nodeName) \
+                    or /javascript/.test attr.value)
+        for name in names
+            el.removeAttribute name
+        true

 Component = Em.Component.extend
     onAnchorClick: Em.on "click", (evt) ->
@@ -18,8 +28,8 @@
         certstatus: (v) -> "#{v.label}"
         link: (v) -> "#{v.label}"
         extlink: (v) -> "#{v.label}"
-        timestamp: (v) ->
-          if v > 0
+        timestamp: (v) ->
+          if v > 0
             moment.unix(v).utc().format("YYYY-MM-DD HH:mm:ss UTC")
           else
             "---"
@@ -30,8 +40,14 @@
         defhash: (v) -> "
#{(for k, w of v then "
#{k}

#{w}
").join ""}
"
         deflist: (v) -> "
#{(for w in v then "
#{w.label}

#{w.value}
").join ""}
"
         ullist: (v) -> "
#{(for w in v then "
#{w}
").join ""}
"
-
+
     formatedValue: Em.computed "content.format", "content.value", ->
-        @get("types")[@get("content.format")||"text"](@get "content.value")
+        e = @get("types")[@get("content.format")||"text"](@get "content.value")
+        $el = $ '
'
+        $el
+            .html e
+            .find ':cleanup'
+        return $el.html()
+

 `export default Component`


copy changes

copy changes

--- client/landing/site.hackathon/coffee/home/AppView.coffee
+++ client/landing/site.hackathon/coffee/home/AppView.coffee
@@ -211,146 +211,166 @@

         JOIN THE WORLD’S FIRST GLOBAL HACKATHON #WFGH

-
Announcing the world's first global virtual hackathon IN THE BROWSER.

-          Join today to save your spot and win $10,000 in cash.

+
Announcing the world's first global virtual hackathon. Let's hack together!

+          Join today and save your spot to win $10,000 in cash prizes.

#{@getStats()}

-
Calling Developers of the World

-
All countries, All ages. Let's CODE!

-
-
Software is shaping our world. Yet developers are still far apart, and
-        lacking a level playing field. Our browsers are now so strong to do everything
-        but bringing us together to write code.
-

-
-
This event wants to connect developers worldwide and help them code together.

-
-
-
If you are looking for team members, post on the #wfgh channel
-        on Koding and then jump into private chats to discuss your ideas and start
-        recruiting! Your post should clearly articulate what type of skill set you are
-        looking for any what type of skill set you have. e.g.: I am a php developer
-        looking for a backend database team member.

+
Developers of the World

+

+
Let's Hack Together!

+
Traditional hackathons are all about the location and although we love the good old
+        fashioned way of hacking together an awesome project, our browsers are now strong enough
+        that distance is of no consequence when it comes to creating awesome projects. We can
+        and should get together to write code and create awesome projects, regardless of
+        where we are.
+

+
Welcome to the World’s First Global Hackathon (#wfgh)!

+
+
This event is intended to connect developers across the globe and get them to  code
+        together irrespective of their locations. You will problem solve and build with old or
+        new team members and try to win!
+

How does it work?

-
 Sign up above, then we will send you a short questionnaire and help you get ready.
-        Nothing else is needed.

-
+
 First, sign up using the simple form above. We will send you a short questionnaire
+        that will help us understand a little bit more about you and your team’s background.
+        We promise to keep it short and sweet.
+

+
+
Applications can come from individuals or teams of up to 5, however each team member
+        needs to be a contributing team member (writing code or designing). If you are an
+        individual who is selected and are looking for team members, post a message on the
+        #wfgh channel on Koding.
+        Your post should clearly articulate what type of skill set you are looking for and what
+        type of skill set you have. e.g.: I am a nodeJS developer looking for a backend
+        database team member. Once you get a response, jump into private chats on Koding
+        itself to discuss your ideas and start recruiting!

How do I get accepted?

-
Our judges decide who gets in. And they can select anyone they like.
-        We can accomodate only select number of applications to keep it sane, so we will limit total applications to 5,000.
-        First come first served. Apply today, and you will receive a note from us if you're accepted as soon as a judge approves.
-

-

-

-
 How do I qualify?

+
We expect a lot of you to apply but to keep things sane, we will be limiting the
+        final competition to a 1000 teams. Our panel of judges will decide who will be part
+        of the competition. Their decision will be based on factors like location, team size,
+        project work on github, social presence, etc. Applications are being reviewed on a first
+        come first serve basis so apply today and if approved, you will receive an email from
+        us with further instructions. We will also let you know if your application is not approved.
+

+

+

+
What is the theme for the Hackathon?

+
48 hours before the start of the event, we will provide a theme for the event. Your task
+      will be to use the API’s of one (or more) of our API partners and create a project that
+      addresses the theme of the event. The theme will be announced on the
+      #wfgh channel on Koding
+       so make sure and mark your calendars!
+

+

+
 What are the rules?

+
Our goal is to ensure that all teams have a level playing field; therefore it is
+        imperative that all code, design, assets, etc… must be created during the duration
+        of the event. No exceptions. You can brainstorm ideas prior to the event, however
+        any assets or code used as part of your submission must have been created during the event.
+        The only exception to this rule is the usage of publicly available material. This includes:
+        public code snippets, images, open source libraries and projects, public APIs, etc. You
+        get the picture. Play fair!
+

+

+        Note: If your team qualifies for a prize, you are automatically subject to a code
+        and asset review to ensure that the above rule has been adhered to.
+
+

+

+
What are the prizes?

+

+
$10,000 cash prize from Koding, split amongst 1 to 3 teams (100%, 70%-30%, 50%-30%-20%)

+
The top prize winners will be offered interviews with investors on our judging panel
+        (RTP Ventures and Greycroft Partners).

+
More to come!

+

+

+

+
Who will eventually own the projects created?

+
+
You will retain full ownership and rights to your creation. Be super awesome and have fun! Get
+        creative, meet new people, make new friends and problem solve with them.
+

+

+

+
What is the schedule?

-
You are a developer, you have good looking Github/Stackoverflow profile page.

-
You're a designer, you have a good looking dribbble or behance profile.

-
Linkedin work experience is also acceptable.

-
If you are not a developer or a designer, you should apply and let a developer and designer vouch for you.

-

-

-

-
Yes, you can code alone, if that's your style.

-
-
However, we will favor groups, in the end, the point is to code together, most importantly
-        with people that from other countries. In your application form tell us about your skills,
-        and what kind of people you want to pair up with, we will select some developers and send you
-        their github links, if you like them - we will organize a chat room for you to get ready.
-

-

-

-
Already have a group?

-
-
Awesome. Now it's time to pick an awesome project.

-

-

-
Ideas?

-
-
 We will provide a list of ideas that are endorsed by our sponsors.
-        If you pick one of those ideas or something similar, with the approval of the sponsors
-        you will get to win their rewards. For example, if you choose to hack on Firebase API,
-        and you win the competition, you receive the winner prize plus Firebase special prizes.

-
-
Our goal is to ensure that all teams have a level playing field
-        therefore it is imperative that all code, design, assets, etc must be
-        created during the duration of the event. No exceptions. You can brainstorm
-        ideas prior to the event however any assets or code used as part of your
-        submission must have been created during the event. The only exception
-        to this rule is the usage of publicly available material.
-        This includes: code snippets, images, open source libraries, etc. 3rd
-        party services like APIs, open source projects, open source libraries
-        and frameworks are all all allowed.You get the picture. Play fair!

-
-
Note: If your team qualifies for a prize, you are automatically
-        subject to a code and asset review to ensure that the above rule has been
-        adhered to.

-

-

-
Ownership

-
You will retain full ownership and rights to your creation.

-        Be super awesome and have fun!

-        Get creative and have a great time. Meet new people, make new friends and problem solve with them.

-

-

-
Schedule

-
-

-
Now - Registration open

-
Nov 20th - Applications are closed. Last notifications are sent to teams/individuals who were accepted into the hackathon

-
Nov 29th - Day 1
-

-
0900 PDT  Announcement of topics on #WFGH

-
0901 PDT  Let the hacking begin!

-

-

-
Nov 30th - Day 2
+
Now - Registration open.

+
Nov 16th - Applications are closed. Final notifications are sent to teams/individuals who were accepted.

+
Nov 18th, 1000 PDT - Hackathon theme is announced on the  #wfgh channel on Koding

+
Nov 22th - Day 1 Let the hacking begin!

+
Nov 23rd - Day 2 of the Hackathon

0000 – 2200 PDT Hacking continues

-
2200 – 2230 PDT Teams submit their projects

+
2330 – 0000 PDT Teams submit their projects)

+

+
Nov 25th - Winners are notified via email and winning projects are listed for public viewing.

+

+

+

+
What is the judging process?

+
Due to the large number of teams and potential hosting pitfalls that can come with, we request that
+        each team submit their project using a Koding VM. Don’t worry, you don’t need a paid account. If you
+        submit your project and your VM is turned off due to inactivity, we will turn it on for you.
+

+
Judging will happen in three rounds:

+

+
Round 1: All projects submitted for this round are distributed (ad-hoc) to our judges panel and
+          they will evaluate it based on API’s used, complexity of solution, adherence to the theme, team size,
+          geolocation of team, etc. Selected projects move to round 2.

-
December 3rd - Winners are notified via email and winning projects are listed

-

-

-

-
Prizes

-
-

-
$10,000 cash prize from Koding, split amongst 1 to 3 teams (100%, 70%-30%, 50%-30%-20%)

-
The top prize winners will be offered to have interviews with investors

-
Sponsors will offer prizes to the winner and/or to the teams that they selected.

-
$10,000 Amazon AWS Credit

-
$2,000/month in free Rackspace cloud for 12 months.

-
$1,000/month in free Digital Ocean for 12 months.

+
Round 2: Teams reaching this stage will have their projects evaluated on stricter versions of
+          the same criteria above and will be exposed to our entire judging staff. Each judge gets to assign
+          points (1-10) and the top 10 teams scoring the most move to the final round.
+

+
Round 3: Judges meet (virtually of course) for a live call to discuss and pick the final 3.
+

-

-
+

+

+
How to submit your project

+
Send the following details to wfgh@koding.com
+

+
Koding VM URL where the judges can see your project.

+
A brief description of your project (not more than 250 words).

+
A brief introduction to your team members (who did what).

+
How your project addresses the theme of the hackathon.

+
What tools did you use to collaborate.

+

+
Your submission should have a time label less than 23:59 PDT, Nov 23rd 2014.
+          Submissions received after the deadline will not be considered. No exceptions.
+

+

+

+
Questions?

+
Send us an email at wfgh@koding.com

+

Judges

-
+

       Copyright © #{(new Date).getFullYear()} Koding, Inc
       Pricing
       Community
       About
-      Legal
+      Legal

     """


WIP: fixed board editing bug

WIP: fixed board editing bug

--- client/src/app/game/board/editBoardChipPinsDialog.coffee
+++ client/src/app/game/board/editBoardChipPinsDialog.coffee
@@ -56,15 +56,15 @@
   if 'processor' of liaison.model
     $scope.kind = 'Processor'
     $scope.type = liaison.model.processor
-    typeDef = currentGame.version.processors[$scope.type]
+    typeDef = currentGame.version.processors[$scope.type] || currentGame.standardLibrary.processors[$scope.type]
   else if 'switch' of liaison.model
     $scope.kind = 'Switch'
     $scope.type = liaison.model.switch
-    typeDef = currentGame.version.switches[$scope.type]
+    typeDef = currentGame.version.switches[$scope.type] || currentGame.standardLibrary.switches[$scope.type]
   else if 'circuit' of liaison.model
     $scope.kind = 'Circuit'
     $scope.type = liaison.model.circuit
-    typeDef = currentGame.version.circuits[$scope.type]
+    typeDef = currentGame.version.circuits[$scope.type] || currentGame.standardLibrary.circuits[$scope.type]
   else
     throw new Error('Model is not a processor, switch, or circuit')


Added new commands to the list...

Added new commands to the list...

--- src/dispatch.coffee
+++ src/dispatch.coffee
@@ -10,7 +10,7 @@

 # commands to copy from shelljs into globals.
 ShellCommands = [
-  "cat", "cd", "chmod", "cp", "dirs", "env", "exit", "find", "grep",
+  "cat", "cd", "chmod", "cp", "dirs", "env", "exit", "grep",
   "ls", "mkdir", "mv", "popd", "pushd", "pwd", "rm", "sed", "test", "which"
 ]


rounding x, y coordinates

rounding x, y coordinates

--- src/drawable.coffee
+++ src/drawable.coffee
@@ -42,17 +42,17 @@
     center = self.center()

     if I.rotation
-      I.transform = Matrix.translation(center.x, center.y)
+      I.transform = Matrix.translation(center.x.round(), center.y.round())
       I.transform = I.transform.concat(Matrix.rotation(I.rotation))
       I.transform = I.transform.concat(Matrix.HORIZONTAL_FLIP) if I.hflip
       I.transform = I.transform.concat(Matrix.VERTICAL_FLIP) if I.vflip
       I.transform = I.transform.concat(Matrix.translation(-I.width/2, -I.height/2))
     else
       # Assumes I.x and I.y are top-left
-      I.transform = Matrix.translation(I.x, I.y)
+      I.transform = Matrix.translation(I.x.round(), I.y.round())

       if I.hflip || I.vflip
-        I.transform = Matrix.translation(center.x, center.y)
+        I.transform = Matrix.translation(center.x.round(), center.y.round())
         I.transform = I.transform.concat(Matrix.HORIZONTAL_FLIP) if I.hflip
         I.transform = I.transform.concat(Matrix.VERTICAL_FLIP) if I.vflip
         I.transform = I.transform.concat(Matrix.translation(-I.width/2, -I.height/2))


Fixed the previewsContainer option bug.

Fixed the previewsContainer option bug.

Fixes #73

--- src/dropzone.coffee
+++ src/dropzone.coffee
@@ -86,8 +86,8 @@
     # processQueue()
     enqueueForUpload: yes

-    # Can be a jQuery or HTML element that will hold the file previews
-    # If null, the dropzone element will be used
+    # A CSS selector or HTML element for the file previews container.
+    # If null, the dropzone element itself will be used
     previewsContainer: null

@@ -272,7 +272,15 @@
       # Remove the fallback
       fallback.parentNode.removeChild fallback

-    @previewsContainer = if @options.previewsContainer then createElement(@options.previewsContainer) else @element
+    if @options.previewsContainer
+      if typeof @options.previewsContainer == "string"
+        @previewsContainer = document.querySelector @options.previewsContainer
+      else if @options.previewsContainer.nodeType?
+        @previewsContainer = @options.previewsContainer
+      throw new Error "Invalid `previewsContainer` option provided. Please provide a CSS selector or a plain HTML element." unless @previewsContainer?
+    else
+      @previewsContainer = @element
+

     @init()

@@ -663,7 +671,7 @@
 Dropzone.isBrowserSupported = ->
   capableBrowser = yes

-  if window.File and window.FileReader and window.FileList and window.Blob and window.FormData
+  if window.File and window.FileReader and window.FileList and window.Blob and window.FormData and document.querySelector
     unless "classList" of document.createElement "a"
       capableBrowser = no
     else


Removed some doubting from fact vote

Removed some doubting from fact vote

--- core/app/backbone/views/facts/fact_vote_area_view.coffee
+++ core/app/backbone/views/facts/fact_vote_area_view.coffee
@@ -24,8 +24,6 @@
   events:
     'click .js-button-believes': ->
       @collection.clickCurrentUserOpinion 'believes'
-    'click .js-button-doubts': ->
-      @collection.clickCurrentUserOpinion 'doubts'
     'click .js-button-disbelieves': ->
       @collection.clickCurrentUserOpinion 'disbelieves'

@@ -43,7 +41,6 @@
     switch model.get('type')
       when 'believes'    then @ui.avatarsBelievesRegion
       when 'disbelieves' then @ui.avatarsDisbelievesRegion
-      when 'doubts'      then @ui.avatarsDoubtsRegion

   onRender: ->
     @_updateActiveCell()


rename blip to prefix

rename blip to prefix

--- src/factoids.coffee
+++ src/factoids.coffee
@@ -28,9 +28,9 @@
   robot.router.get "/#{robot.name}/factoids", (req, res) =>
     res.end JSON.stringify @factoids.data, null, 2

-  blip = process.env.HUBOT_FACTOID_PREFIX or '!'
+  prefix = process.env.HUBOT_FACTOID_PREFIX or '!'

-  robot.hear new RegExp("^[#{blip}]([\\w\\s-]{2,}\\w)( @.+)?", 'i'), (msg) =>
+  robot.hear new RegExp("^[#{prefix}]([\\w\\s-]{2,}\\w)( @.+)?", 'i'), (msg) =>
     fact = @factoids.get msg.match[1]
     to = msg.match[2]
     if not fact? or fact.forgotten


add showShifts button

add showShifts button

--- imports/ui/components/allProjects/allProjects.coffee
+++ imports/ui/components/allProjects/allProjects.coffee
@@ -20,7 +20,7 @@
 			id: index + 1
 			_id: project._id
 			name: project.name
-			showAdmins: 'Show admins...'
+			showAdmins: 'Show admins... | Show shifts...'

 	$('#projectTable').html('').footable
 		columns: columns


Use native-ui theme in Atom

Use native-ui theme in Atom

--- atom/config.cson
+++ atom/config.cson
@@ -25,7 +25,7 @@
       "welcome"
     ]
     themes: [
-      "one-light-ui"
+      "native-ui"
       "one-light-syntax"
     ]
   editor:


Remove Atom nim settings

Remove Atom nim settings

--- atom/config.cson
+++ atom/config.cson
@@ -68,9 +68,6 @@
 ".python.source":
   editor:
     softTabs: false
-".nim.source":
-  editor:
-    tabLength: 2
 ".shell.source":
   editor:
     tabLength: 2


Hide Linter panel when empty

Hide Linter panel when empty

The default for hidePanelWhenEmpty was changed to false in
linter-ui-default v1.6.1.

--- atom/config.cson
+++ atom/config.cson
@@ -114,7 +114,8 @@
     disableWhenNoJshintrcFileInPath: true
   "linter-shellcheck": {}
   "linter-ui-default":
-    panelHeight: 69
+    hidePanelWhenEmpty: true
+    panelHeight: 95
     showPanel: true
     showTooltip: false
   "markdown-preview":


Don't hang request in the event of a spelling backend error

--- services/web/app/coffee/Features/Spelling/SpellingController.coffee
+++ services/web/app/coffee/Features/Spelling/SpellingController.coffee
@@ -12,4 +12,5 @@
 		request(url: Settings.apis.spelling.url + url, method: req.method, headers: req.headers, json: req.body, timeout:TEN_SECONDS)
 		.on "error", (error) ->
 			logger.error err: error, "Spelling API error"
+			res.status(500).end()
 		.pipe(res)


turn on syntax check for all users

turn on syntax check for all users

--- services/web/public/coffee/ide/pdf/controllers/PdfController.coffee
+++ services/web/public/coffee/ide/pdf/controllers/PdfController.coffee
@@ -74,7 +74,8 @@
 			$scope.pdf.renderingError = true

 		# abort compile if syntax checks fail
-		$scope.stop_on_validation_error = localStorage("stop_on_validation_error:#{$scope.project_id}") or ide.$scope?.user?.betaProgram
+		$scope.stop_on_validation_error = localStorage("stop_on_validation_error:#{$scope.project_id}")
+		$scope.stop_on_validation_error ?= true # turn on for all users by default
 		$scope.$watch "stop_on_validation_error", (new_value, old_value) ->
 			if new_value? and old_value != new_value
 				localStorage("stop_on_validation_error:#{$scope.project_id}", new_value)


Enabling markdown preview

Enabling markdown preview

Former-commit-id: eebf3dfcfdff0ce024d7b84b3a7dffee200de728

--- Libraries/Atom/Config/config.cson
+++ Libraries/Atom/Config/config.cson
@@ -27,7 +27,6 @@
       "bookmarks"
       "language-mustache"
       "autosave"
-      "markdown-preview"
       "autocomplete-snippets"
       "dev-live-reload"
       "styleguide"


delete time fix

delete time fix

--- app/assets/javascripts/application.coffee
+++ app/assets/javascripts/application.coffee
@@ -11,7 +11,7 @@
     $saved.hide()

     inputDelay = 3000
-    eraseDelay = 1000
+    eraseDelay = 300
     fadeOutDelay = 1000
     eraseInterval = 0
     eraseTimeout = 0


Fixed truncation (this function is becoming a -mess-)

--- app/assets/javascripts/calendar.js.coffee
+++ app/assets/javascripts/calendar.js.coffee
@@ -41,10 +41,14 @@
       if start_at < bar_length
         if end_at > bar_length
           if(item.data("start")?)
+            console.log(current_hour)
             new_time = new Date(current_time.getTime())
+            new_time.setHours(0)
             new_time.setSeconds(0)
             new_time.setMinutes(Math.ceil(new_time.getMinutes()/10)*10)
+            new_time.setTime(new_time.getTime() + current_hour*60*60*1000)
             item.data("start",new_time.toLocalISOString())
+            item.attr("data-start", new_time.toLocalISOString())
           item.height(end_at - bar_length)
         else
           item.data("remove", true)


Search previous conditions if open the page

--- app/assets/javascripts/sequence.js.coffee
+++ app/assets/javascripts/sequence.js.coffee
@@ -4,6 +4,9 @@
   if seq
     $("#fragment").val(seq)

+    unless window.location.search
+      $('button').click()
+
   $('button').on "click", ->
     fragment = $("#fragment").val()
     if fragment


Corrected bad regex

Corrected bad regex


Fix margins on scatterplot

Fix margins on scatterplot

--- app/controllers/interactive/graphs.coffee
+++ app/controllers/interactive/graphs.coffee
@@ -59,7 +59,7 @@
       @graph = new Histogram { el: '#graph', channel: 'graph', height: 310, width: 512 }
     else
       @setPressed $('[data-variables="scatterplot"]')
-      @graph = new Scatterplot { el: '#graph', channel: 'graph', height: 310, width: 512 }
+      @graph = new Scatterplot { el: '#graph', channel: 'graph', height: 310, width: 512, margin: { left: 50, top: 20, bottom: 40 } }

   setGraph: =>
     if @graphType is 'histogram'
@@ -67,7 +67,7 @@
       @graph = new Histogram { el: '#graph', channel: 'graph', height: 310, width: 512 }
     else
       @xAxisItem.find('label').html 'I\'d like to see how...'
-      @graph = new Scatterplot { el: '#graph', channel: 'graph', height: 310, width: 512 }
+      @graph = new Scatterplot { el: '#graph', channel: 'graph', height: 310, width: 512, margin: { left: 50, top: 20, bottom: 40 } }

   # Graph interface functions
   setGraphType: (e) =>


Moved all Button logic to subclassess

Moved all Button logic to subclassess

--- app/js/jail_iframe/classes/buttons.coffee
+++ app/js/jail_iframe/classes/buttons.coffee
@@ -1,26 +1,4 @@
-class Button
-  constructor: ->
-    @frame = new FactlinkJailRoot.ControlIframe()
-    @frame.setContent($.parseHTML(@content.trim())[0])
-    @$el = $(@frame.frameBody.firstChild)
-
-  _bindCallbacks: (callbacks) ->
-    @_robustHover = new FactlinkJailRoot.RobustHover @$el, callbacks
-    @$el.on 'click', -> callbacks.click?()
-
-  startHovering: => @frame.addClass 'hovered'
-  stopHovering: => @frame.removeClass 'hovered'
-
-  # TODO: do all updates of different buttons in one pass
-  _updatePositionRegularly: ->
-    $(window).on 'resize', @_updatePosition
-    @_interval = setInterval @_updatePosition, 1000
-    @_updatePosition()
-
-  _updatePosition: =>
-
-
-class FactlinkJailRoot.CreateButton extends Button
+class FactlinkJailRoot.CreateButton
   content: """

@@ -35,11 +13,13 @@
   """

   constructor: ->
-    super
+    @frame = new FactlinkJailRoot.ControlIframe()
+    @frame.setContent($.parseHTML(@content.trim())[0])
+    @$el = $(@frame.frameBody.firstChild)

     @_robustHover = new FactlinkJailRoot.RobustHover @$el,
-      mouseenter: => @startHovering()
-      mouseleave: => @stopHovering()
+      mouseenter: => @frame.addClass 'hovered'
+      mouseleave: => @frame.removeClass 'hovered'

     @$el.on 'mousedown', (event) -> event.preventDefault() # To prevent de-selecting text
     @$el.on 'click', @_onClick
@@ -80,8 +60,12 @@
     @_visible = false

-
-class IconButton extends Button
+class IconButton
+
+  constructor: ->
+    @frame = new FactlinkJailRoot.ControlIframe()
+    @frame.setContent($.parseHTML(@content.trim())[0])
+    @$el = $(@frame.frameBody.firstChild)

   destroy: =>
     @frame.destroy()
@@ -90,6 +74,22 @@
     clearInterval @_interval
     @$boundingBox?.remove()

+  _bindCallbacks: (callbacks) ->
+    @_robustHover = new FactlinkJailRoot.RobustHover @$el, callbacks
+    @$el.on 'click', -> callbacks.click?()
+
+  startHovering: => @frame.addClass 'hovered'
+  stopHovering: => @frame.removeClass 'hovered'
+
+  # TODO: do all updates of different buttons in one pass
+  _updatePositionRegularly: ->
+    $(window).on 'resize', @_updatePosition
+    @_interval = setInterval @_updatePosition, 1000
+    @_updatePosition()
+
+  _updatePosition: =>
+
+

 class FactlinkJailRoot.ShowButton extends IconButton
   content: '

'


allow root nodes to be fixed indepedent of other nodes

--- app/scripts/alchemy/core/drawnodes.coffee
+++ app/scripts/alchemy/core/drawnodes.coffee
@@ -10,8 +10,14 @@
                     .on('dblclick', alchemy.interactions.nodeDoubleClick)
                     .on('click', alchemy.interactions.nodeClick)

+    rootNodes = nodeEnter.filter((d) -> return d.node_type == "root")
+    nonRootNodes = nodeEnter.filter((d) -> return d.node_type != "root")
+
     if not conf.fixNodes
-        nodeEnter.call(alchemy.interactions.drag)
+        nonRootNodes.call(alchemy.interactions.drag)
+
+    if not conf.fixRootNodes
+        rootNodes.call(alchemy.interactions.drag)

     # if conf.locked then nodeEnter.call node_drag else nodeEnter.call force.drag


redirect when Facebook adds _=_ to the url

--- app/assets/javascripts/components/dynamic-router.cjsx
+++ app/assets/javascripts/components/dynamic-router.cjsx
@@ -1,5 +1,5 @@
 React = require("react")
-{Router, Routes, Route, Link} = require 'react-router'
+{Router,Redirect, Routes, Route, Link} = require 'react-router'
 MainHeader                    = require '../partials/main-header'
 HomePage                      = require './home-page'
 Mark                          = require './mark'
@@ -9,15 +9,15 @@

   getInitialState: ->
     project: null
-
+
   componentDidMount: ->
-    $.getJSON '/projects', (result) =>
+    $.getJSON '/projects', (result) =>
       @setState project:           result.project
-      @setState home_page_content: result.project.home_page_content
+      @setState home_page_content: result.project.home_page_content
       @setState pages:             result.project.pages
         # DEBUG CODE
         # , => console.log 'PROJECT: ', @state.project
-
+
   controllerForPage: (page) ->
     React.createClass
       displayName: "#{page.name}Page"
@@ -33,31 +33,32 @@
       <MainHeader pages={@state.pages} />
       <div className="main-content">
         <Routes>
-          <Route
-            path='/'
-            handler={HomePage}
-            name="root"
+          <Redirect from="_=_" to="/" />
+          <Route
+            path='/'
+            handler={HomePage}
+            name="root"
             content={@state.home_page_content} />
-          <Route
-            path='/mark'
-            handler={Mark}
+          <Route
+            path='/mark'
+            handler={Mark}
             name='mark'
             workflow={(workflow for workflow in workflows when workflow.name is 'mark')[0]} />
-          <Route
-            path='/transcribe'
-            handler={Transcribe}
+          <Route
+            path='/transcribe'
+            handler={Transcribe}
             name='transcribe'
             workflow={(workflow for workflow in workflows when workflow.name is 'transcribe')[0]} />

           { @state.pages?.map (page, key) =>
-              <Route
-                path={'/'+page.name}
-                handler={@controllerForPage(page)}
+              <Route
+                path={'/'+page.name}
+                handler={@controllerForPage(page)}
                 name={page.name} key={key} />
           }
-
+
         </Routes>
       </div>
     </div>

-module.exports = DynamicRouter+module.exports = DynamicRouter


display text row focus based on tool_task_description.type

--- app/assets/javascripts/components/subject-viewer.cjsx
+++ app/assets/javascripts/components/subject-viewer.cjsx
@@ -284,7 +284,10 @@
             }

             { # ROW FOCUS TOOL -------------------------------------------
-              if @props.workflow.name is "transcribe" and @state.subject.location.spec.tool is 2
+              console.log 'WORKFLOW: ', @props.workflow.name
+              console.log 'TASK: ', @state.subject.tool_task_description.task
+              if @props.workflow.name is "transcribe" and @state.subject.tool_task_description.type is "textRowTool"
+                console.log 'BLAH'
                 markHeight = @state.subject.location.spec.yLower - @state.subject.location.spec.yUpper
                 <g>

@@ -332,6 +335,9 @@
                     fill        = "rgba(0,0,0,0.6)"
                   />
                 </g>
+              else
+                console.log 'NO BLAH'
+                <g></g>
             }

           </svg>


OX-766

--- app/assets/javascripts/oxalis/geometries/plane.coffee
+++ app/assets/javascripts/oxalis/geometries/plane.coffee
@@ -182,7 +182,7 @@
                 @plane.volumeTexture.image.data.set(dataBuffer)
               @flycam.hasNewTexture[@planeID] = true

-            if volumeBuffer and not (@binary["volume"]? or @binary["segmentation"]?)
+            if volumeBuffer and not (@model.binary["volume"]? or @model.binary["segmentation"]?)
               # Generate test pattern
               #for i in [0...512]
               #  for j in [0...512]


fix button text in dialog (russian translation)

--- app/assets/javascripts/uploadcare/locale/ru.js.coffee
+++ app/assets/javascripts/uploadcare/locale/ru.js.coffee
@@ -27,7 +27,7 @@
           drag: 'Перетащите файл сюда'
           nodrop: 'Загрузка файлов с вашего компьютера'
           or: 'или'
-          button: 'Выбрать файлы'
+          button: 'Выберите файл c компьютера'
           also: 'Вы также можете загрузить файлы используя'
           tabNames:
             facebook: 'Facebook'


Make use of CoffeeScript's try-like syntax.

--- application/chrome/content/wesabe/ofx/Response.coffee
+++ application/chrome/content/wesabe/ofx/Response.coffee
@@ -83,8 +83,7 @@
     return @__investmentAccounts__

   hasOFX: ->
-    documentElement = this.responseXML.documentElement
-    return documentElement?.tagName.toLowerCase() == 'ofx'
+    return @responseXML.documentElement?.tagName.toLowerCase() == 'ofx'

   # Check to see if the server returned any errors in the OFX response.
   isSuccess: ->


Fix typo

Fix typo

--- atom/renderer/lib/web-view/web-view-attributes.coffee
+++ atom/renderer/lib/web-view/web-view-attributes.coffee
@@ -166,7 +166,7 @@
     if useragent then opts.useragent = useragent

     guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId)
-    guestContents.loadUrl @getValue(), urlOptions
+    guestContents.loadUrl @getValue(), opts

 # Attribute specifies HTTP referrer.
 class HttpReferrerAttribute extends WebViewAttribute


Remove unneccessary return.

Remove unneccessary return.

--- app/static/coffee/production-chart.coffee
+++ app/static/coffee/production-chart.coffee
@@ -148,5 +148,3 @@
     group

   legend vis, 166, 40, legendData
-
-  return


debugging

debugging

--- app.coffee
+++ app.coffee
@@ -18,9 +18,8 @@

 app.post '/keyin', (req, res) ->
   twiml = new twilio.TwimlResponse()
-  console.log req.json, req.body
+  console.log req
   twiml.say 'Success!'
-
   twiml.say "You entered #{req.json['Digits']}"
   res.set 'Content-Type', 'text/xml'
   res.send new Buffer twiml.toString()


removing nowJS server side

removing nowJS server side

--- app.coffee
+++ app.coffee
@@ -40,15 +40,15 @@
 server.listen(8984)
 console.log 'listening...'

-everyone = now.initialize(server)
-everyone.now.distributeMessage = (message) ->
-  everyone.now.receiveMessage(this.now.name, message)
+# everyone = now.initialize(server)
+# everyone.now.distributeMessage = (message) ->
+#   everyone.now.receiveMessage(this.now.name, message)

-everyone.connected(  (message) ->
-  everyone.now.receiveMessage(this.now.name, message)
-)
+# everyone.connected(  (message) ->
+#   everyone.now.receiveMessage(this.now.name, message)
+# )

-everyone.now.updateElement = (className, top, left) ->
-  everyone.now.receiveElement(className, top, left)
+# everyone.now.updateElement = (className, top, left) ->
+#   everyone.now.receiveElement(className, top, left)

 people = ['Animal', 'Beaker', 'Piggy', 'Kermit']


TRIED THE FILESYSTEM THING I READ ON THE INTERNET.

--- app.coffee
+++ app.coffee
@@ -19,6 +19,7 @@
 amqp = require("amqp")
 global.mongo = require('mongodb')
 redis = require('redis')
+fs = require('fs')

 startServer = ->
   console.log "=> Booting Node.js faye [#{global.app_env}]"
@@ -65,8 +66,9 @@

   if app_env == "production"
     # Start listening to a unix socket.
-    faye.listen config.faye.socket
-    console.log "=> Node.js cloudsdale-faye started on ws://#{config.faye.host}:#{config.faye.port}#{config.faye.path} (socket)"
+    fs.unlink config.faye.socket, ->
+      faye.listen config.faye.socket
+      console.log "=> Node.js cloudsdale-faye started on ws://#{config.faye.host}:#{config.faye.port}#{config.faye.path} (socket)"
   else
     # Start listening to the faye server port.
     faye.listen config.faye.port


Add start fun = issue

Add start fun = issue

--- app.coffee
+++ app.coffee
@@ -5,6 +5,7 @@
 get = require './libs/get.js'
 checks = require './libs/checks.js'
 parse = require './libs/parse.js'
+exec = require 'child_process'
 # Read instances

 start = (args, dir) ->
@@ -20,5 +21,20 @@
     console.log 'Ruby version '+ parsed.ruby+' is required. \nPlease consider using Docker'
   if parsed.python != undefined && process.env.WEB_DOCKER != true
     console.log 'Python version '+ parsed.python+' is required. \nPlease consider using Docker'
+  log = exec.spawn(parsed.start)
+  log.stdout.on('data', (data) ->
+    return 'h'
+    console.log data
+  )
+
+  log.stderr.on('data', (data) ->
+    return 'h'
+    console.log data
+    # body...
+  )
+
+  log.on
+  return 'Done'
+  # start

 start('test', 'instances')


Turn text property updating class variable to a local variable

--- framer/InputLayer.coffee
+++ framer/InputLayer.coffee
@@ -51,10 +51,10 @@
 		@_setTextProperties()

 		# All inherited properties
-		@_textProperties =
+		textProperties =
 			{@fontFamily, @fontSize, @lineHeight, @fontWeight, @color, @backgroundColor, @width, @height}

-		for property, value of @_textProperties
+		for property, value of textProperties

 			@on "change:#{property}", (value) =>
 				@_setTextProperties()


log improved and url code confusion fixed

--- client/Framework/core/utils.coffee
+++ client/Framework/core/utils.coffee
@@ -734,13 +734,10 @@
       dataType    : "json"

     request.done (data)=>
-      if data.id
-        url = data.id
-
-      callback url, data
-
-    request.error ->
-      log "url shorten error, returing self."
+      callback data?.id or url, data
+
+    request.error ({status, statusText, responseText})->
+      error "url shorten error, returing self as fallback.", status, statusText, responseText
       callback url

   # deprecated ends


mixpanel: be a proper poor man

mixpanel: be a proper poor man

--- client/app/MainApp/mixpanel.coffee
+++ client/app/MainApp/mixpanel.coffee
@@ -130,5 +130,5 @@
         "$email"        : email
         "$created"      : createdAt
         "Status"        : type
-        "Randomizer"    : Math.floor((Math.random()*4)+1)
+        "Randomizer"    : KD.utils.getRandomNumber 4
       mixpanel.name_tag "#{nickname}.kd.io"


add a line in toast

add a line in toast

--- client/app/components/toast.coffee
+++ client/app/components/toast.coffee
@@ -82,7 +82,7 @@
             content     : React.DOM.pre
                 style: "max-height": "300px",
                 "word-wrap": "normal",
-                    getErrors
+                    getErrors '\n'
         LayoutActionCreator.displayModal modal


--- src/jsconfig.coffee
+++ src/jsconfig.coffee
@@ -75,13 +75,16 @@
                 else
                     deep_set conf, target, process.env[key]

+            # these contains all options that differ from their default value
+            optsdiff = {}
             if opts?
                 # merge options into config
                 for key, target of map.opts
                     continue unless opts[key]
                     # only set when differs from defaults
                     continue if opts[key] is deep_get(defaults, target)
-                    deep_set conf, target, opts[key]
+                    deep_set optsdiff, target, opts[key]
+                    deep_set conf,     target, opts[key]
             # remove loader code
             for key in ['defaults', 'set', 'cli', 'load']
                 delete config[key]
@@ -89,6 +92,12 @@
             defaults = {}
             # insert all loaded values
             inplace_merge config, conf
+            # monkey patch merge to apply set opts to config again
+            old_merge = @merge
+            @merge = ->
+                result = old_merge(arguments...)
+                inplace_merge config, optsdiff
+                return result
             # when sync call, callback is undefined
             callback?.apply this, arguments


extract get_enml_and_title_from_md()

extract get_enml_and_title_from_md()

--- app/assets/javascripts/app.coffee
+++ app/assets/javascripts/app.coffee
@@ -60,6 +60,28 @@
     p = noteManager.get_all_notes().then (notes) ->
       vm.set_note_list(notes)
     p.catch (error) -> alert('reload_local_note_list() failed')
+
+  vm.get_enml_and_title_from_md = (md) ->
+    html_div_hidden = $('#md_html_div_hidden')
+    enml = enmlRenderer.getEnmlFromElement(
+      html_div_hidden,
+      vm.render_html,
+      md
+    )
+    title = 'New Note - Markever'
+    if html_div_hidden.find('h1').size() > 0
+      text = html_div_hidden.find('h1').text()
+      title = text if text.trim().length > 0
+    else if html_div_hidden.find('h2').size() > 0
+      text = html_div_hidden.find('h2').text()
+      title = text if text.trim().length > 0
+    else if html_div_hidden.find('h3').size() > 0
+      text = html_div_hidden.find('h3').text()
+      title = text if text.trim().length > 0
+    else if html_div_hidden.find('p').size() > 0
+      text = html_div_hidden.find('p').text()
+      title = text if text.trim().length > 0
+    return {enml: enml, title: title}

   # ------------------------------------------------------------------------------------------------------------------
   # Debugging methods
@@ -177,6 +199,7 @@
   # ------------------------------------------------------------------------------------------------------------------
   vm.change_current_note = (guid, title, md) ->
     vm.set_guid(guid) if guid?
+    # FIXME generate title from md
     vm.set_title(title) if title?
     vm.set_md_and_update_editor(md) if md?
     # render html
@@ -420,33 +443,17 @@
     $('#loading-modal').modal('hide')

   # ------------------------------------------------------------------------------------------------------------------
-  # save note
+  # sync current note to remote
   # ------------------------------------------------------------------------------------------------------------------
   vm.save_note = ->
     if vm.saving_note == false
       # set status
       vm.saving_note = true
-      # fill the hidden html div
-      html_div_hidden = $('#md_html_div_hidden')
-      enml = enmlRenderer.getEnmlFromElement(
-        html_div_hidden,
-        vm.render_html,
-        vm.get_md()
-      )
-      # set title to content of first H1, H2, H3, H4 tag
-      vm.set_title('New Note - Markever')
-      if html_div_hidden.find('h1').size() > 0
-        text = html_div_hidden.find('h1').text()
-        vm.set_title(text) if text.trim().length > 0
-      else if html_div_hidden.find('h2').size() > 0
-        text = html_div_hidden.find('h2').text()
-        vm.set_title(text) if text.trim().length > 0
-      else if html_div_hidden.find('h3').size() > 0
-        text = html_div_hidden.find('h3').text()
-        vm.set_title(text) if text.trim().length > 0
-      else if html_div_hidden.find('p').size() > 0
-        text = html_div_hidden.find('p').text()
-        vm.set_title(text) if text.trim().length > 0
+      # get enml and title
+      _enml_and_title = vm.get_enml_and_title_from_md(vm.get_md())
+      enml = _enml_and_title['enml']
+      title = _enml_and_title['title']
+      vm.set_title(title)
       # invoke the api
       # TODO handle error
       apiClient.notes.save({


proper

proper

--- node/fabricate.coffee
+++ node/fabricate.coffee
@@ -529,7 +529,7 @@
       external_url: "http://www.lempertz-online.de/gldet_gb.asp?v=k1026400009980073900011&mkat=0&mablos=737&msb=&martist=0"
       id: uuid()
       image_url: "http://static1.artsy.net/auction_lots/51d041844c91c616610005a0/thumbnail.jpg"
-      image_versions: [thumbnail]
+      image_versions: ['thumbnail']
       medium_text: "Screenprint on canvas"
       organization: "Lempertz"
       price_realized_text: "€140,300"


support passing an element as well as selector

--- client/lanes/react/Viewport.coffee
+++ client/lanes/react/Viewport.coffee
@@ -13,7 +13,7 @@
         height:         'number'
         el:             'element'
         selector:       'string'
-        domRoot:        'element'
+        container:      'element'
         reactRoot:      'object'
         lanes:          'element'
         modalProps:     'object'
@@ -27,14 +27,17 @@
     constructor: ->
         super
         ALL_INSTANCES.push(this)
-        return unless @selector
-        @domRoot = document.body.querySelector(@selector)
-        _.dom(@domRoot).addClass('lanes-root')
-        Lanes.fatal("Root selector #{@selector} not found") unless @domRoot
-        _.dom(@domRoot).html = "
"
-        this.lanes = @domRoot.querySelector('.lanes')
+        unless (@container or (@selector and
+                (@container = document.body.querySelector(@selector))))
+            console.warn("Unable to render without container or valid selector")
+            return

-        Lanes.lib.ResizeSensor(@domRoot, _.debounce( =>
+        _.dom(@container).addClass('lanes-root')
+        Lanes.fatal("Root selector #{@selector} not found") unless @container
+        _.dom(@container).html = "
"
+        this.lanes = @container.querySelector('.lanes')
+
+        Lanes.lib.ResizeSensor(@container, _.debounce( =>
             @_updateDimensions()
         , 250))
         this._updateDimensions()
@@ -47,7 +50,7 @@

     onBoot: ->
-        prev = _.dom(this.domRoot.previousElementSibling)
+        prev = _.dom(this.container.previousElementSibling)
         if @useHistory
             @initializeHistory()
         else
@@ -81,6 +84,7 @@
     close: ->
         @hideModal()
         @_historyStopListening?()
+        @container.remove()

     _updateDimensions: ->
         this.set


fixed meteor icon

fixed meteor icon

--- client/views/login/services.coffee
+++ client/views/login/services.coffee
@@ -10,7 +10,7 @@
 			switch service
 				when 'meteor-developer'
 					serviceName = 'Meteor'
-					icon = 'dot-circle-o'
+					icon = 'meteor'
 				when 'github'
 					serviceName = 'GitHub'
 					icon = 'github-circled'


remove enableSliderControls

remove enableSliderControls

--- app/controllers/classifier.coffee
+++ app/controllers/classifier.coffee
@@ -305,7 +305,6 @@
     @frameSlider.hide()
     markingSurfaces = document.getElementsByClassName("marking-surface")
     @resizeElements(markingSurfaces, 255) # image sizing for 4up view
-    @enableSliderControls true
     @fourUpButton.attr 'disabled', true
     @flickerButton.attr 'disabled', false
     @el.attr 'flicker', "false"
@@ -320,7 +319,6 @@
     @nextFrame.show()
     @playButton.show()
     @frameSlider.show()
-    @enableSliderControls false
     @flickerButton.attr 'disabled', true
     @fourUpButton.attr 'disabled', false
     @el.attr 'flicker', "true"
@@ -334,10 +332,6 @@
       for surface in @markingSurfaceList
         for tool in surface.tools
           tool.render()
-
-  enableSliderControls: (bool) ->
-    document.getElementById("frame-slider").disabled = bool
-    @playButton.attr 'disabled', bool

   resizeElements: (elements, newSize) ->
     for element in elements


Fix cache not working.

Fix cache not working.

--- workers/social/lib/social/models/recurly/subscription.coffee
+++ workers/social/lib/social/models/recurly/subscription.coffee
@@ -46,7 +46,7 @@
     unless forceRefresh
       JRecurlySubscription.all selector, callback
     else
-      JRecurlySubscription.one {}, (err, sub)=>
+      JRecurlySubscription.one selector, (err, sub)=>
         callback err  if err
         unless sub
           @updateCache userCode, -> JRecurlySubscription.all selector, callback


Remove unneeded second param to removeAttribute

--- src/space-pen.coffee
+++ src/space-pen.coffee
@@ -87,7 +87,7 @@
       outlet = element.getAttribute('outlet')
       element = $(element)
       view[outlet] = element
-      element[0].removeAttribute('outlet', null)
+      element[0].removeAttribute('outlet')

     undefined


test/ide/search: update for teams

test/ide/search: update for teams

--- client/test/lib/ide/search.coffee
+++ client/test/lib/ide/search.coffee
@@ -1,144 +1,170 @@
 helpers    = require '../helpers/helpers.js'
 ideHelpers = require '../helpers/idehelpers.js'
-
+utils = require '../utils/utils.js'
+async = require 'async'
+teamsHelpers = require '../helpers/teamshelpers.js'
 paneSelector = '.pane-wrapper .kdsplitview-panel.panel-1 .application-tab-handle-holder'
+activeEditorSelector = '.pane-wrapper .kdsplitview-panel.panel-1 .kdtabpaneview.active .ace_content'

 module.exports =

+  before: (browser, done) ->

-  findInFiles: (browser) ->
+    ###
+    * we are creating users list here to send invitation and join to team
+    * so we will be able to run our test for different kind of member role
+    ###
+    targetUser1 = utils.getUser no, 1
+    targetUser1.role = 'member'

-    user = helpers.beginTest(browser)
-    helpers.waitForVMRunning(browser)
+    users = [
+      targetUser1
+    ]

-    contentSearchModalSelector  = '.content-search-modal'
-    findInFilesSelector         = '.kdlistview-contextmenu li.search-in-all-files'
-    matchedWordSelector         = '.content-search-result pre p.match'
-    activeUntitledFileSelector  = "#{paneSelector} .untitledtxt.active"
-    activeEditorSelector        = '.pane-wrapper .kdsplitview-panel.panel-1 .kdtabpaneview.active .ace_content'
-    fileNameSelector            = '.content-search-result .filename > span'
+    queue = [
+      (next) ->
+        teamsHelpers.inviteAndJoinWithUsers browser, users, (result) ->
+          next null, result
+      (next) ->
+        teamsHelpers.buildStack browser, (res) ->
+          next null, res

-    ideHelpers.openNewFile(browser)
-    ideHelpers.openContextMenu(browser)
+      # go to IDE url
+      (next) ->
+        teamUrl = helpers.getUrl yes
+        url = "#{teamUrl}/IDE"
+        browser.url url, -> next null
+    ]

-    browser
-      .waitForElementVisible     findInFilesSelector, 20000
-      .click                     findInFilesSelector
-      .waitForElementVisible     contentSearchModalSelector, 20000
-      .setValue                  contentSearchModalSelector + ' input[name=findInput]', 'Hello World from Python by Koding'
-      .click                     contentSearchModalSelector + ' button.search'
-      .waitForElementVisible     paneSelector + ' .search-result', 20000 # Assertion
-      .waitForElementNotPresent  activeUntitledFileSelector, 20000 # Assertion
-      .pause                     5000
-      .getText                   fileNameSelector, (result = {}) ->
+    async.series queue, (err, result) ->
+      done()  unless err

-        fileName  = result.value.split('/')?.reverse()[0]
-        lowercase = fileName?.replace(/\./g, '').toLowerCase()
+  search: (browser) ->

-        return browser.end() unless lowercase
+    user = utils.getUser()

-        editorSelector    = ".panel-1 .kdtabpaneview.active.#{lowercase} .ace_content"
+    queue = [
+
+      # findInFiles
+      (next) ->
+        contentSearchModalSelector  = '.content-search-modal'
+        findInFilesSelector         = '.kdlistview-contextmenu li.search-in-all-files'
+        matchedWordSelector         = '.content-search-result pre p.match'
+        activeUntitledFileSelector  = "#{paneSelector} .untitledtxt.active"
+        fileNameSelector            = '.content-search-result .filename > span'
+
+        ideHelpers.openNewFile browser, ->
+
+          ideHelpers.openContextMenu browser, ->
+
+            browser
+              .waitForElementVisible     findInFilesSelector, 20000
+              .click                     findInFilesSelector
+              .waitForElementVisible     contentSearchModalSelector, 20000
+              .setValue                  contentSearchModalSelector + ' input[name=findInput]', '# for examples'
+              .click                     contentSearchModalSelector + ' button.search'
+              .waitForElementVisible     paneSelector + ' .search-result', 20000 # Assertion
+              .waitForElementNotPresent  activeUntitledFileSelector, 20000 # Assertion
+              .pause                     5000
+              .getText                   fileNameSelector, (result = {}) ->
+
+                fileName  = result.value.split('/')?.reverse()[0]
+                lowercase = fileName?.replace(/\./g, '').toLowerCase()
+
+                return next null unless lowercase
+
+                editorSelector    = ".panel-1 .kdtabpaneview.active.#{lowercase} .ace_content"
+
+                browser
+                  .waitForElementVisible     matchedWordSelector, 20000
+                  .click                     matchedWordSelector
+                  .waitForElementNotPresent  paneSelector + '.search-result .active', 20000 # Assertion
+                  .waitForElementVisible     editorSelector, 20000
+                  .pause                     3000 # wait for content
+                  .assert.containsText       editorSelector, '# for examples'
+                  .pause 1, -> next null
+
+      # jumpToFile
+      (next) ->
+
+        searchModalSelector  = '.file-finder'
+        findInFilesSelector  = '.kdlistview-contextmenu li.find-file-by-name'
+        filename = 'test.txt'
+        filenameClassname = 'testtxt'
+        helpers.createFileFromMachineHeader browser, user, filename, yes, (res) ->
+
+          ideHelpers.openNewFile(browser)
+          ideHelpers.openContextMenu(browser)
+
+          paneSelector         = ".pane-wrapper .kdsplitview-panel .application-tab-handle-holder .#{filenameClassname}"
+
+          browser
+            .waitForElementVisible   findInFilesSelector, 20000
+            .click                   findInFilesSelector
+            .waitForElementVisible   searchModalSelector, 20000
+            .setValue                searchModalSelector + ' input.text', "#{filename}"
+            .waitForElementVisible   searchModalSelector + ' .file-item:first-child', 20000
+            .click                   searchModalSelector + ' .file-item:first-child'
+            .waitForElementVisible   ".kdtabhandle.#{filenameClassname}.active", 20000 # Assertion
+            .waitForElementVisible   paneSelector, 20000 # Assertion
+            .pause 1, -> next null
+
+      # saveUntitledFile
+      (next) ->
+        ideHelpers.createAndSaveNewFile browser, user, null, ->
+          next null
+
+      # toggleInvisibleFiles
+      (next) ->
+
+        fileName     = ".#{helpers.getFakeText().split(' ')[0]}.txt"
+        filePath     = "/home/#{user.username}"
+        fileSelector = ".file-container span[title='#{filePath}/#{fileName}']"
+
+        helpers.createFileFromMachineHeader(browser, user, fileName, no)
+        ideHelpers.clickItemInMachineHeaderMenu(browser, '.refresh')

         browser
-          .waitForElementVisible     matchedWordSelector, 20000
-          .click                     matchedWordSelector
-          .waitForElementNotPresent  paneSelector + '.search-result .active', 20000 # Assertion
-          .waitForElementVisible     editorSelector, 20000
-          .pause                     3000 # wait for content
-          .assert.containsText       editorSelector, 'Hello World from Python by Koding'
-          .end()
+          .pause   4000 # wait for file create complete
+          .element 'css selector', fileSelector, (result) ->

+            if result.status is 0
+              ideHelpers.clickItemInMachineHeaderMenu(browser, '.toggle-invisible-files')

-  jumpToFile: (browser) ->
+              browser
+                .waitForElementNotPresent fileSelector, 20000 # Assertion
+                .pause 1, -> next null

-    helpers.beginTest(browser)
-    helpers.waitForVMRunning(browser)
+            else
+              ideHelpers.clickItemInMachineHeaderMenu(browser, '.toggle-invisible-files')

-    searchModalSelector  = '.file-finder'
-    findInFilesSelector  = '.kdlistview-contextmenu li.find-file-by-name'
-    paneSelector         = '.pane-wrapper .kdsplitview-panel .application-tab-handle-holder .pythonpy'
+              browser
+                .waitForElementVisible  fileSelector, 20000 # Assertion
+                .pause 1, -> next null

-    ideHelpers.openNewFile(browser)
-    ideHelpers.openContextMenu(browser)
+      # openAnExistingFileAndSave
+      (next) ->
+        text     = helpers.getFakeText()
+        fileName = ideHelpers.createAndSaveNewFile browser, user, text, ->

-    browser
-      .waitForElementVisible   findInFilesSelector, 20000
-      .click                   findInFilesSelector
-      .waitForElementVisible   searchModalSelector, 20000
-      .setValue                searchModalSelector + ' input.text', 'python'
-      .waitForElementVisible   searchModalSelector + ' .file-item:first-child', 20000
-      .click                   searchModalSelector + ' .file-item:first-child'
-      .waitForElementVisible   '.ws-tabview .kdtabview .pythonpy.active', 20000 # Assertion
-      .waitForElementVisible   paneSelector, 20000 # Assertion
-      .end()
+          ideHelpers.closeFile(browser, fileName, user)
+          ideHelpers.openAnExistingFile(browser, user, fileName, text)

-
-  saveUntitledFile: (browser) ->
-
-    user = helpers.beginTest(browser)
-    helpers.waitForVMRunning(browser)
-
-    ideHelpers.createAndSaveNewFile(browser, user)
-
-    browser.end()
-
-
-  toggleInvisibleFiles: (browser) ->
-
-    user = helpers.beginTest(browser)
-    helpers.waitForVMRunning(browser)
-
-    fileName     = ".#{helpers.getFakeText().split(' ')[0]}.txt"
-    filePath     = "/home/#{user.username}"
-    fileSelector = ".file-container span[title='#{filePath}/#{fileName}']"
-
-    helpers.createFileFromMachineHeader(browser, user, fileName, no)
-    ideHelpers.clickItemInMachineHeaderMenu(browser, '.refresh')
-
-    browser
-      .pause   4000 # wait for file create complete
-      .element 'css selector', fileSelector, (result) ->
-
-        if result.status is 0
-          ideHelpers.clickItemInMachineHeaderMenu(browser, '.toggle-invisible-files')
+          ideHelpers.setTextToEditor(browser, text)

           browser
-            .waitForElementNotPresent fileSelector, 20000 # Assertion
-            .end()
+            .assert.containsText    activeEditorSelector, text # Assertion

-        else
-          ideHelpers.clickItemInMachineHeaderMenu(browser, '.toggle-invisible-files')
+          ideHelpers.saveFile(browser)
+          ideHelpers.closeFile(browser, fileName, user)
+          ideHelpers.openAnExistingFile(browser, user, fileName, text)

           browser
-            .waitForElementVisible  fileSelector, 20000 # Assertion
-            .end()
+            .waitForTextToContain activeEditorSelector, text # Assertion
+            .pause 1, -> next null
+    ]

+    async.series queue

-  openAnExistingFileAndSave: (browser) ->
-
-    activeEditorSelector = '.pane-wrapper .kdsplitview-panel.panel-1 .kdtabpaneview.active'
-
-
-    user = helpers.beginTest(browser)
-    helpers.waitForVMRunning(browser)
-
-    text     = helpers.getFakeText()
-    fileName = ideHelpers.createAndSaveNewFile(browser, user, text)
-
-    ideHelpers.closeFile(browser, fileName, user)
-    ideHelpers.openAnExistingFile(browser, user, fileName, text)
-
-    text = helpers.getFakeText()
-
-    ideHelpers.setTextToEditor(browser, text)
-
-    browser
-      .assert.containsText    activeEditorSelector, text # Assertion
-
-    ideHelpers.saveFile(browser)
-    ideHelpers.closeFile(browser, fileName, user)
-    ideHelpers.openAnExistingFile(browser, user, fileName, text)
-
-    browser.waitForTextToContain activeEditorSelector, text # Assertion
-
+  after: (browser) ->
     browser.end()


Redirect happening before login is finished processing

Fixed bug in which redirect to dashboardRoute was happening too fast (before loginWithPassword() was finished processing) resulting in the Router evaluating dashboardRoute while Meteor.user() is still null.

Now we redirect to dashboardRoute only after login is finished processing.

--- client/views/signUp/signUp.coffee
+++ client/views/signUp/signUp.coffee
@@ -127,11 +127,19 @@
           if  _.contains([
             'USERNAME_AND_EMAIL',
             'EMAIL_ONLY'], AccountsEntry.settings.passwordSignupFields)
-            Meteor.loginWithPassword(email, password)
+            Meteor.loginWithPassword(email, password, (error) ->
+              if error
+                Session.set('entryError', error.reason)
+              else
+                Router.go AccountsEntry.settings.dashboardRoute
+            )
           else
-            Meteor.loginWithPassword(username, password)
-
-          Router.go AccountsEntry.settings.dashboardRoute
+            Meteor.loginWithPassword(username, password, (error) ->
+              if error
+                Session.set('entryError', error.reason)
+              else
+                Router.go AccountsEntry.settings.dashboardRoute
+            )
       else
         Session.set('entryError', i18n("error.signupCodeIncorrect"))
         return


pass through message when no more submissions.

--- lms/static/coffee/src/staff_grading/staff_grading.coffee
+++ lms/static/coffee/src/staff_grading/staff_grading.coffee
@@ -112,7 +112,7 @@
       if response.submission
         @data_loaded(response.submission, response.rubric)
       else
-        @no_more()
+        @no_more(response.message)
     else
       @error(response.error)

@@ -137,10 +137,10 @@
     @score = null
     @state = state_grading

-  no_more: () ->
+  no_more: (message) ->
     @submission = null
     @rubric = null
-    @message = 'Nothing to grade'
+    @message = message
     @state = state_no_data

   render_view: () ->