Select grammars based on first 10 lines of content, not the entire file

--- src/tokenized-buffer.coffee
+++ src/tokenized-buffer.coffee
@@ -67,7 +67,7 @@
     if grammar.injectionSelector?
       @retokenizeLines() if @hasTokenForSelector(grammar.injectionSelector)
     else
-      newScore = grammar.getScore(@buffer.getPath(), @buffer.getText())
+      newScore = grammar.getScore(@buffer.getPath(), @getGrammarSelectionContent())
       @setGrammar(grammar, newScore) if newScore > @currentGrammarScore

   setGrammar: (grammar, score) ->
@@ -75,7 +75,7 @@

     @grammar = grammar
     @rootScopeDescriptor = new ScopeDescriptor(scopes: [@grammar.scopeName])
-    @currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText())
+    @currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @getGrammarSelectionContent())

     @grammarUpdateDisposable?.dispose()
     @grammarUpdateDisposable = @grammar.onDidUpdate => @retokenizeLines()
@@ -106,8 +106,11 @@
     @emit 'grammar-changed', grammar if Grim.includeDeprecatedAPIs
     @emitter.emit 'did-change-grammar', grammar

+  getGrammarSelectionContent: ->
+    @buffer.getTextInRange([[0, 0], [10, 0]])
+
   reloadGrammar: ->
-    if grammar = atom.grammars.selectGrammar(@buffer.getPath(), @buffer.getText())
+    if grammar = atom.grammars.selectGrammar(@buffer.getPath(), @getGrammarSelectionContent())
       @setGrammar(grammar)
     else
       throw new Error("No grammar found for path: #{path}")


Ignore null elements.

Ignore null elements.

--- client/hook-field.coffee
+++ client/hook-field.coffee
@@ -1,14 +1,16 @@
 @hook_field = (n, {type, attr, name}, elm) ->
-  h = (x) ->
-        t = $ x.target
-        v = if type is "boolean"
-              if t.is (":checked") then "true" else "false"
-            else
-              t.val()
-        if attr
-          n.attr name, v
-        else
-          n.text v
-  elm.change h
-  elm.blur h
-  elm.click h
+  if elm
+    h = (x) ->
+          t = $ x.target
+          v = if type is "boolean"
+                if t.is (":checked") then "true" else "false"
+              else
+                t.val()
+          if attr
+            n.attr name, v
+          else
+            n.text v
+    elm.change h
+    elm.blur h
+    elm.click h
+  elm


IDE: loadCollaborativeIDE when route has social channel ID

--- client/ide/routes.coffee
+++ client/ide/routes.coffee
@@ -96,7 +96,10 @@
     KD.getSingleton('router').handleRoute "/IDE/#{machineLabel}/#{workspaceSlug}"

-  routeToLatestWorkspace = ->
+  routeToLatestWorkspace = ({ params : { machineLabel } }) ->
+
+    # we assume that if machineLabel is all numbers it is the channelId - SY
+    return loadCollaborativeIDE machineLabel  if machineLabel and /^[0-9]+$/.test machineLabel

     machine = KD.userMachines.first
     return putVMInWorkspace machine  if machine
@@ -108,6 +111,24 @@
         return

       putVMInWorkspace machines.first
+
+
+  loadCollaborativeIDE = (id) ->
+
+    KD.singletons.socialapi.channel.byId { id }, (err, channel) ->
+
+      return routeToLatestWorkspace() if err
+
+      try
+        for workspace in KD.userWorkspaces when workspace.channelId is channel.id
+          machine   = (KD.userMachines.filter (m) -> m.uid is workspace.machineUId)[0]
+          username  = if workspace.owner then workspace.owner else KD.nick()
+          channelId = channel.id
+          return loadIDE { machine, workspace, username, channelId }
+
+      catch e
+        return routeToLatestWorkspace()
+

   KD.registerRoutes 'IDE',


Make minor, idiomatic changes to ostest.coffee.

--- ostest.coffee
+++ ostest.coffee
@@ -47,7 +47,7 @@
   portIndex = 0
   port = ports[portIndex]

-  if host == '' then return
+  if host is '' then return

   hasFoundPort = () ->
     return foundPort or numberOfPortsChecked is (ports.length - 1)
@@ -87,4 +87,4 @@
 fs.readFile process.argv[2], 'utf-8', (err, data) ->
   if err then throw err
   hosts = data.toString().split '\n'
-  hosts.forEach processHost
+  processHost host for host in hosts


Code cleanup

Code cleanup

--- queue_tea.coffee
+++ queue_tea.coffee
@@ -129,10 +129,6 @@
     @cursor.write(header.padRight(" ", @width - header.length))
     @cursor.reset().bg.reset()

-    # for i, line in @src._log(@height).split("\n")
-    #   @cursor.goto(0, i+1)
-    #   #@cursor.write(line)
-
     @cursor.goto(0, @height+2)
     @cursor.show()
     @cursor.restorePosition() if restore
@@ -144,8 +140,6 @@

   constructor: ->
     new ServiceSelector().on "select", @_onServiceSelect
-    #@_onServiceSelect()
-    @_logLines = []
     @_sensors = {}

@@ -170,29 +164,11 @@
       fields.push "#{k.capitalize()}: #{v}\u00B0C"
     fields.join("  ")

-  _log: (height) =>
-    log = ""
-    blankLines = height - @_logLines.length - 1
-
-    if blankLines < 0
-      @_logLines = @_logLines[0..height-1]
-    else
-      log += "\n" for i in [0..blankLines]
-
-    log += @_logLines.join("\n") + "\n" if @_logLines.length > 0
-    return log
-
   _append: (s, prefix = "") ->
     stdout.write(prefix + s + "\n")
-    # for line in s.trim().split("\n")
-
-    #   @_logLines.shift() if @_logLines.length >= @cli.height
-    #   @_logLines.push(prefix + line)

   _parseLine: (line) =>
     line = line.toString()
-    #console.log line
-    #@_append(line, "> ")
     words = line.split(/\s/)[0]
     cmd = words.shift()
     if cmd == "help" then @_appendHelp()


Remove nulled variable

Remove nulled variable

--- src/theme-manager.coffee
+++ src/theme-manager.coffee
@@ -263,10 +263,9 @@
       @emit 'stylesheets-changed'

   applyStylesheet: (path, text, type='bundled') ->
-    styleElement = null
-
     styleId = @stringToId(path)
     styleElement = @stylesheetElementForId(styleId)
+
     if styleElement?
       @emit 'stylesheet-removed', styleElement.sheet
       styleElement.textContent = text


using inline-block for the header (fix for FF)

--- src/views/HeaderView.coffee
+++ src/views/HeaderView.coffee
@@ -20,7 +20,7 @@
       # padding el
       spacer = document.createElement "span"
       spacer.innerHTML = " "
-      spacer.style.display = "block"
+      spacer.style.display = "inline-block"
       spacer.style.float = "left"
       spacerWidth = 0
       spacerWidth += @g.zoomer.get "labelWidth" if @g.vis.get "labels"


add panel class to match HW builder

add panel class to match HW builder

--- src/components/questions/sections-chooser.cjsx
+++ src/components/questions/sections-chooser.cjsx
@@ -35,7 +35,7 @@
   render: ->
     help = Help.forCourseId(@props.courseId)

-

+


command: deprecate --join

command: deprecate --join

--- command.coffee
+++ command.coffee
@@ -81,7 +81,22 @@
   process.argv[0] = 'coffee'

   opts.output = path.resolve opts.output  if opts.output
-  opts.join   = path.resolve opts.join    if opts.join
+  if opts.join
+    opts.join = path.resolve opts.join
+    console.error '''
+
+    The --join option is deprecated and will be removed in a future version.
+
+    If for some reason it's necessary to share local variables between files,
+    replace...
+
+        $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee
+
+    with...
+
+        $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js
+
+    '''
   for source in opts.arguments
     source = path.resolve source
     compilePath source, yes, source


Distances set up for kilometres as well.

--- src/core/javascripts/controllers/map.js.coffee
+++ src/core/javascripts/controllers/map.js.coffee
@@ -210,6 +210,7 @@
     pi = Math.PI;
     R = 6371  #equatorial radius
     distances = []
+    distances_kilometers = []

     lat1 = latlong.lat();
     lon1 = latlong.lng();
@@ -231,6 +232,7 @@
               Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(rLat1) * Math.cos(rLat2);
       c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
       d = R * c;
+      k = d
       # convert to miles
       d = d * 0.621371192

@@ -238,10 +240,14 @@
         marker.setVisible(false)

       marker.distance = d
+      marker.distance_kilometers = k
       distances.push marker if d < $scope.range_limit
-
-    distances.sort (a,b)->
-      a.distance - b.distance
+      distances_kilometers.push marker if k < $scope.range_limit
+      items = [distances, distances_kilometers]
+      for item in items
+        item.sort (a, b)->
+          a.distance - b.distance
+          a.distance_kilometers - b.distance_kilometers

     $scope.shownMarkers = distances.slice(0,$scope.numSearchResults)
     localBounds = new google.maps.LatLngBounds()


added compiling of home file in compile.coffee

--- compile.coffee
+++ compile.coffee
@@ -24,6 +24,10 @@
         console.log 'Writing page ' + sidebarFilename
         fs.writeFileSync sidebarFilename, eco.render(sidebarTemplate, { manifest: manifest, baseUrl: options.baseUrl })

+        homeFilename = path.join options.out, 'index.html'
+        console.log 'Writing page ' + homeFilename
+        fs.writeFileSync homeFilename, eco.render(manifest.home)
+
         for entry in manifest.tableOfContent
             filename = path.join options.out, 'page-' + entry.index + '.html'
             console.log 'Writing page ' + filename


fix(build): remove rb-popover regex from ignoreCustomFragments

--- rapid-build.cson
+++ rapid-build.cson
@@ -50,7 +50,6 @@
 					/<rba-code(\s*?.*?)*?rba-code>/gi
 					/\s?<rb-icon\s|<\/rb-icon>\s?/gi
 					/\s?<rba-copy[^]*?rba-copy>\s?/gi
-					/\s?<rb-popover[^]*?rb-popover>\s?/gi
 				]

 	order: # build will merge this with dev or prod


Added pubsub to ws

Added pubsub to ws

--- static/js/web_socket.coffee
+++ static/js/web_socket.coffee
@@ -7,7 +7,7 @@

 	onMessage: (event) ->
 		data = JSON.parse event.data
-		console.log data
+		PubSub.publish data.type, data

 	register: ->
 		@ws.send @apiKey
@@ -15,3 +15,5 @@

 $ ->
 	new WSocket(options.apiKey)
+	PubSub.subscribe "log_message", (type, data) ->
+		console.log data.message


chapters: ensure correct order

chapters: ensure correct order

--- src/javascripts/extensions/chaptermarks.coffee
+++ src/javascripts/extensions/chaptermarks.coffee
@@ -14,6 +14,7 @@

   cleanData: =>
     @data.start = @data.start.split('.')[0]
+    @data.startInSeconds = Utils.hhmmssToSeconds(@data.start)

   render: =>
     @elem = $(@defaultHtml)
@@ -60,10 +61,14 @@
   renderPanel: =>
     @panel = $(@panelHtml)
     @panel.hide()
-    @chaptermarks.forEach((item, index, array) =>
-      item.elem = new ChapterMark(item, @click).render()
-
-      @panel.find('ul').append(item.elem)
+    marks = _.map(@chaptermarks, (item) =>
+      new ChapterMark(item, @click)
+    )
+    marks = _.sortBy(marks, (mark) =>
+      mark.data.startInSeconds
+    )
+    _.map(marks, (mark) =>
+      @panel.find('ul').append(mark.render())
     )

   attachEvents: =>


Support arbitrary keys in Map

Support arbitrary keys in Map

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -760,15 +760,22 @@
     keys = (map (__ string_, _labelName), labels)
     assignCompile ctx, form, (irMap keys, compiledItems)

-uniformCollectionCompile = (ctx, form, items, collectionType) ->
+
+uniformCollectionCompile = (ctx, form, items, collectionType, moreConstraints = []) ->
+  {constraints, itemType, compiled} = uniformCollectionItemsCompile ctx, items
+  form.label = 'operator' if not isCall form
+  form.tea = new Constrained (join moreConstraints, constraints),
+      new TypeApp collectionType, itemType
+  compiled
+
+uniformCollectionItemsCompile = (ctx, items) ->
   itemType = ctx.freshTypeVariable star
   compiledItems = termsCompile ctx, items
   for item in items
     unify ctx, itemType, item.tea.type
-  form.label = 'operator' if not isCall form
-  form.tea = new Constrained (concatMap _constraints, (tea for {tea} in items)),
-    new TypeApp collectionType, itemType
-  compiledItems
+  constraints: (concatMap _constraints, (tea for {tea} in items))
+  itemType: itemType
+  compiled: compiledItems

 # arrayToConses = (elems) ->
 #   if elems.length is 0
@@ -1497,6 +1504,21 @@
     items = _arguments call
     compiledItems = uniformCollectionCompile ctx, call, items, hashsetType
     assignCompile ctx, call, (irSet compiledItems)
+
+ms.Map = ms_Map = (ctx, call) ->
+  if hashset = ctx.assignTo()
+    # TODO:
+    throw new Error "matching on sets not supported yet"
+  else
+    args = _arguments call
+    if args.length % 2 != 0
+      malformed args[args.length - 1], 'Missing value for key'
+    [labels, items] = unzip pairs args
+    compiledLabels = uniformCollectionItemsCompile ctx, labels
+    keyType = applyKindFn hashmapType, compiledLabels.itemType
+    compiledItems = uniformCollectionCompile ctx, call, items, keyType,
+      compiledLabels.constraints
+    assignCompile ctx, call, (irMap compiledLabels.compiled, compiledItems)

 # Before assign the correct type to plus
 # ms['+'] = ms_plus = (ctx, call) ->
@@ -3972,6 +3994,17 @@
   """
   """(elem? "a" data)""", yes

+  'create Map'
+  """
+    data (Map 3 "a" 5 "b")
+
+    at (macro [key in]
+      (: (Fn k (Map k i) i))
+      (Js.call (Js.access in "get") {key}))
+  """
+  """(at 5 data)""", 'b'
+
+
   # TODO: support matching with the same name
   #       to implement this we need the iife to take as arguments all variables
   #       with the same names, since JavaScript shadows it too strongly and


Suggest types in declared types

Suggest types in declared types

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -1386,13 +1386,17 @@
   {fails: [{conflicts, types}]} = matchType inferredType.type.type, copyOrigin (updatedDeclaredType.type.type), declaredType.type.type
   [fromInferred, fromDeclared] = types
   [t1, t2] = sortBasedOnOriginPosition fromInferred, fromDeclared
-  ctx.extendSubstitution substitutionFail
-    message: "declared type is too general, " +
-      if t1 is fromInferred
-        "inferred #{printType types[0]}, got #{print originOf types[1]}"
-      else
-        "got #{print originOf types[1]}, inferred #{printType types[0]}"
-    conflicts: conflicts
+  # Dont report for fake types
+  declaringType = originOf fromDeclared
+  if isFake declaringType
+    declaringType.inferredType = fromInferred
+  else
+    inferred = "inferred #{printType fromInferred}"
+    got = "got #{print declaringType}"
+    ctx.extendSubstitution substitutionFail
+      message: "declared type is too general, " +
+        if t1 is fromInferred then "#{inferred}, #{got}" else "#{got}, #{inferred}"
+      conflicts: conflicts

 topLevelExpression = (ctx, expression) ->
   ctx.bareDefine()
@@ -5300,6 +5304,8 @@
       (map printer, join [type.type], type.constraints).join ' '
     else
       printer type.type
+  else
+    printer type

 forallToHumanReadable = (type) ->
   notConstrained = (type) ->


Wip type system

Wip type system

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -1105,6 +1105,40 @@
     scope[id] = true
   scope

+# mycroft = (context, node, environment) ->
+#   if node.label is 'numerical'
+#     environment node.token
+#   else if node.label is 'name'
+#     environment node.token
+#   else if node.type is 'function'
+#     {params, type, doc, body, wheres} = fnDefinition node
+#     mycroft (extendContext context, (paramTypes params, type)), body
+#   else if Array.isArray node
+#     [op, args...] = inside node
+#     # for one arg for now
+#     [s3, c] = mycroft context, op, environment
+#     [s2, a] = mycroft (s3 context), args[0], environment
+#     s1 = unify (s2 c), [a, fresh()]
+
+# paramTypes = (params, fnType) ->
+#   types = inside fnType
+#   if types.length < params.length
+#     throw new Error "Not enough types in type declaration"
+#   context = {}
+#   for param, i in params
+#     context[param.token] = types[i].token
+#   context
+
+
+
+# unify = -> ???
+
+# defaultEnvironment = (name) ->
+#   switch name
+#     when '+' then ['Int', 'Int']
+
+
+
 library = """
 var $listize = function (list) {
   if (list.length == 0) {


Dont throw on unfound instances

Dont throw on unfound instances

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -1276,16 +1276,20 @@
         entailed = entail ctx, unifiedType.constraints, c
       notDeclared = filter (__ _not, isDeclaredConstraint), checked = (substituteList ctx.substitution, constraints)
       try
-        [deferredConstraints, retainedConstraints] = deferConstraints ctx,
-          notDeclared
-      catch e
-        throw new Error "Error when deferring #{name} #{e.message}"
+      {success, error} = deferConstraints ctx, notDeclared
+      if error
+        throw new Error "Error when deferring #{name} #{error}"
+      [deferredConstraints, retainedConstraints] = success
       if _notEmpty retainedConstraints
         ctx.extendSubstitution substitutionFail "#{name}'s context is too weak, missing #{listOf (map printType, retainedConstraints)}"
   else
     # log name, "constraints", (substituteList ctx.substitution, constraints)
-    [deferredConstraints, retainedConstraints] = deferConstraints ctx,
+    {success, error} = deferConstraints ctx,
       (substituteList ctx.substitution, constraints)
+    if error
+      ctx.extendSubstitution substitutionFail error
+      return
+    [deferredConstraints, retainedConstraints] = success
     # Finalizing type again after possibly added substitution when defer constraints
     currentType = substitute ctx.substitution, type
     # log "assign type", name, (printType (addConstraints currentType, retainedConstraints)), (printType quantifyUnbound ctx, (addConstraints currentType, retainedConstraints))
@@ -2449,23 +2453,24 @@
 # Returns deferred and retained constraints
 deferConstraints = (ctx, constraints) ->
   reducedConstraints = reduceConstraints ctx, constraints
-  throw new Error "could not reduce constraints in deferConstraints" unless reducedConstraints
+  if not reducedConstraints.success
+    return reducedConstraints
   fixedVars = ctx.allBoundTypeVariables()
-  impliedConstraints = substituteList ctx.substitution, reducedConstraints
+  impliedConstraints = substituteList ctx.substitution, reducedConstraints.success
   isFixed = (constraint) ->
     # log fixedVars, (printType constraint), (findUnconstrained constraint)
     isSubset fixedVars, (findUnconstrained constraint)
   [deferred, retained] = partition isFixed, impliedConstraints
   # TODO: handle ambiguity when reducedConstraints include variables not in
   # fixedVars or quantifiedVars
-  [deferred, retained]
+  success: [deferred, retained]

 reduceConstraints = (ctx, constraints) ->
   normalized = normalizeConstraints ctx, constraints
-  if normalized
-    simplifyConstraints ctx, normalized
-  else
-    null
+  if normalized.success
+    simplifyConstraints ctx, normalized.success
+  else
+    normalized

 # Normalized constraints have a type variable in their head, they are "abstract"
 # and don't match any one instance
@@ -2483,16 +2488,17 @@
         toNormalize.push instanceContraints...
       else
         # TODO: propogate this as standard error
-        throw new Error "no instance found to satisfy #{safePrintType constraint}"
+        # throw new Error "no instance found to satisfy #{safePrintType constraint}"
+        return error: "No instance found to satisfy #{safePrintType constraint}"
       after = subLimit ctx.substitution
       # There was a functional dependency, renormalize
       if after isnt before
         toNormalize.push normalized...
         normalized = []
   if all normalized
-    normalized
-  else
-    null
+    success: normalized
+  else
+    error: "??Not all normalized??"

 # normalizeConstraint = (ctx, constraint) ->
 #   if isNormalizedConstraint constraint
@@ -2511,7 +2517,7 @@
   for constraint, i in constraints
     if not entailedBySuperClasses ctx, (join requiredConstraints, constraints[i + 1..]), constraint
       requiredConstraints.push constraint
-  requiredConstraints
+  success: requiredConstraints

 # Whether constraints entail constraint
@@ -2867,7 +2873,7 @@
     # if declaredType = ctx.typeForId id
     #   constraintsFromCanonicalType ctx, declaredType, finalType
     # else
-      reduceConstraints ctx, allConstraints
+      (reduceConstraints ctx, allConstraints).success
   if bare and _notEmpty reducedConstraints
     malformed ctx, expression, "Ambiguous class constraints: #{map safePrintType, reducedConstraints}"
     return "null";
@@ -2979,6 +2985,7 @@
   toClassName = (c) -> c.className
   classParams = ctx.classParamsForType constraint
   throw new Error "No params for #{safePrintType constraint}" unless classParams
+  # return "{}" unless classParams
   for className, dict of values classParams
     if chain = findSuperClassChain ctx, className, constraint.className
       return accessList dict, chain
@@ -3013,6 +3020,7 @@
     if toMatchTypes (freshInstance ctx, type).type.types, constraint.types
       return validIdentifier name
   throw new Error "no instance for #{safePrintType constraint}"
+  # return {}

 irFunction = ({name, params, body}) ->
   {ir: irFunctionTranslate, name, params, body}


Updated environment tests

Updated environment tests

--- test/all/environment.coffee
+++ test/all/environment.coffee
@@ -21,6 +21,9 @@
   it 'udefine.env has amd property', ->
     expect(envProp).to.have.property('amd')

+  it 'udefine.env has globals property', ->
+    expect(envProp).to.have.property('globals')
+
   it 'udefine.env.commonjs is a boolean', ->
     expect(envProp.commonjs).to.be.a('boolean')

@@ -29,7 +32,10 @@

   it 'udefine.env.amd is a boolean', ->
     expect(envProp.amd).to.be.a('boolean')
-
+
+  it 'udefine.env.globals is a boolean', ->
+    expect(envProp.globals).to.be.a('boolean')
+
   it 'udefine.env.commonjs is true on Node.js', ->
     if hasModule then expect(envProp.commonjs).to.be.true


fix: preview link (#144)

fix: preview link (#144)

Fix #143

--- menus/asciidoc-preview.cson
+++ menus/asciidoc-preview.cson
@@ -3,8 +3,7 @@
   submenu: [
     label: 'AsciiDoc'
     submenu: [
-      label: 'Toggle Preview'
-    command: 'asciidoc-preview:toggle'
+      label: 'Toggle Preview', command: 'asciidoc-preview:toggle'
     ]
   ]
 ]


Add GET /db/course_instance list by owner and by member

--- server/courses/course_instance_handler.coffee
+++ server/courses/course_instance_handler.coffee
@@ -178,4 +178,20 @@
             return @sendDatabaseError(res, err) if err
             @sendSuccess(res, courseInstances)

+  get: (req, res) ->
+    if ownerID = req.query.ownerID
+      return @sendForbiddenError(res) unless req.user and (req.user.isAdmin() or ownerID is req.user.id)
+      return @sendBadInputError(res, 'Bad ownerID') unless utils.isID ownerID
+      CourseInstance.find {ownerID: mongoose.Types.ObjectId(ownerID)}, (err, courseInstances) =>
+        return @sendDatabaseError(res, err) if err
+        return @sendSuccess(res, (@formatEntity(req, courseInstance) for courseInstance in courseInstances))
+    else if memberID = req.query.memberID
+      return @sendForbiddenError(res) unless req.user and (req.user.isAdmin() or memberID is req.user.id)
+      return @sendBadInputError(res, 'Bad memberID') unless utils.isID memberID
+      CourseInstance.find {members: mongoose.Types.ObjectId(memberID)}, (err, courseInstances) =>
+        return @sendDatabaseError(res, err) if err
+        return @sendSuccess(res, (@formatEntity(req, courseInstance) for courseInstance in courseInstances))
+    else
+      super(arguments...)
+
 module.exports = new CourseInstanceHandler()


Update docker-runner-sharelatex config

Update docker-runner-sharelatex config

--- services/clsi/config/settings.defaults.coffee
+++ services/clsi/config/settings.defaults.coffee
@@ -16,21 +16,16 @@
 		clsiCacheDir: Path.resolve(__dirname + "/../cache")
 		synctexBaseDir: (project_id) -> Path.join(@compilesDir, project_id)

-	# clsi:
-	# 	strace: true
-	# 	archive_logs: true
-	# 	commandRunner: "docker-runner-sharelatex"
-	# 	docker:
-	# 		image: "quay.io/sharelatex/texlive-full"
-	# 		env:
-	# 			PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/texlive/2013/bin/x86_64-linux/"
-	# 			HOME: "/tmp"
-	# 		modem:
-	# 			socketPath: false
-	# 		user: "tex"
-	# 		latexmkCommandPrefix: []
-	# 		# latexmkCommandPrefix: ["/usr/bin/time", "-v"]         # on Linux
-	# 		# latexmkCommandPrefix: ["/usr/local/bin/gtime", "-v"]  # on Mac OSX, installed with `brew install gnu-time`
+#	clsi:
+#		commandRunner: "docker-runner-sharelatex"
+#		docker:
+#			image: "quay.io/sharelatex/texlive-full:2017.1"
+#			env:
+#				HOME: "/tmp"
+#			socketPath: "/var/run/docker.sock"
+#			user: "tex"
+#		expireProjectAfterIdleMs: 24 * 60 * 60 * 1000
+#		checkProjectsIntervalMs: 10 * 60 * 1000

 	internal:
 		clsi:


Use @rhoconlinux's bindings

Use @rhoconlinux's bindings

--- keymaps/script.cson
+++ keymaps/script.cson
@@ -11,6 +11,8 @@

 '.platform-win32 .editor, .platform-linux .editor'
-  'ctrl-i': 'script:run'
+  'shift-ctrl-b': 'script:run'
   'shift-enter': 'script:run'
-  'ctrl-cmd-i': 'script:run-options'
+  'ctrl-w': 'script:close-view'
+  'ctrl-q': 'script:kill-process'
+  'shift-ctrl-alt-o': 'script:run-options'


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/array_extensions.coffee
+++ src/array_extensions.coffee
@@ -1,5 +1,5 @@
 Array::average = ->
-
+  @sum

 ###*
 Returns a copy of the array without null and undefined values.


Pass urlToOpen to AtomWindow constructor

--- src/atom-application.coffee
+++ src/atom-application.coffee
@@ -270,7 +270,6 @@
         configDirPath: fsUtils.absolute('~/.atom')
         devMode: devMode
         resourcePath: @resourcePath
-        urlToOpen: urlToOpen

     packageName = url.parse(urlToOpen).host
     pack = _.find @packages.getAvailablePackageMetadata(), ({name}) -> name is packageName
@@ -278,7 +277,7 @@
       if pack.urlMain
         packagePath = @packages.resolvePackagePath(packageName)
         bootstrapScript = path.resolve(packagePath, pack.urlMain)
-        new AtomWindow({bootstrapScript, @resourcePath, devMode})
+        new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen})
       else
         console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}"
     else


Layer: Fixed checking for mousedown on backdrop for Layer with many child elements.

--- src/base/Layer/Layer.coffee
+++ src/base/Layer/Layer.coffee
@@ -99,7 +99,7 @@
 								type: "click"
 								node: @__backdrop
 								call: (ev) =>
-									CUI.debug "clicked on modal backdrop", bc, @_backdrop
+									# console.debug "clicked on modal backdrop", bc, @_backdrop
 									if not @__layer
 										return

@@ -1196,12 +1196,17 @@
 		node: document.body
 		call: (ev, info) ->

-			layer_elements = DOM.findElements(document.body,
-				"body > .cui-tmpl-layer-root, body > .cui-pane-fill-screen-is-on, body > .cui-layer-prevent-click-thru"
-			)
+			layer_elements = CUI.DOM.find("body > .cui-tmpl-layer-root, body > .cui-pane-fill-screen-is-on, body > .cui-layer-prevent-click-thru")
 			target = ev.getTarget()
-
-			while layer_element = layer_elements.pop()
+			idx = -1
+			len = layer_elements.length
+
+			while true
+				idx = idx + 1
+				if idx == len
+					break
+
+				layer_element = layer_elements[idx]

 				if not CUI.DOM.hasClass(layer_element, "cui-layer-backdrop-policy-click-thru")
 					return


options: remove old test

options: remove old test

--- test/promise.options.coffee
+++ test/promise.options.coffee
@@ -17,7 +17,6 @@
       (options.parent_param_unpropagated is undefined).should.be.true()
       options.global_param.should.be.true()
       callback null, true
-
     m.register 'aparent', (options, callback) ->
       options.global_param.should.be.true()
       options.parent_param_propagated.should.be.true()
@@ -25,32 +24,10 @@
       @achild
         local_param: true
       .then (err, status) -> callback err, true
-
     m.aparent
-      # local_param: true
       parent_param_propagated: true
       parent_param_unpropagated: true
     .then next

-    # old test, we can remove this safely
-    # it.only 'global dont overwrite local options', (next) ->
-    #   logs_global = []
-    #   logs_local = []
-    #   log_global = (msg) -> console.log 'global'; logs_global.push msg
-    #   log_local = (msg) -> console.log 'local'; logs_local.push msg
-    #   mecano log: log_global
-    #   .write
-    #     destination: "#{scratch}/file_1"
-    #     content: 'abc'
-    #     log: log_local
-    #   .write
-    #     destination: "#{scratch}/file_1"
-    #     content: 'def'
-    #     append: true
-    #     log: log_local
-    #   .then (err, changed) ->
-    #     return next err if err
-    #     console.log logs_local
-    #     logs_global.length.should.eql 0
-    #     logs_local.length.should.be.above 1
-    #     next()+
+


Add missing path require

Add missing path require

Closes atom/settings-view#288

--- src/buffered-process.coffee
+++ src/buffered-process.coffee
@@ -1,6 +1,7 @@
 _ = require 'underscore-plus'
 ChildProcess = require 'child_process'
 {Emitter} = require 'event-kit'
+path = require 'path'

 # Extended: A wrapper which provides standard error/output line buffering for
 # Node's ChildProcess.


fix hash check to use 'v' field instead of version

--- services/document-updater/app/coffee/ShareJsUpdateManager.coffee
+++ services/document-updater/app/coffee/ShareJsUpdateManager.coffee
@@ -26,7 +26,7 @@
 		logger.log project_id: project_id, doc_id: doc_id, update: update, "applying sharejs updates"
 		jobs = []
 		# record the update version before it is modified
-		incomingUpdateVersion = update.version
+		incomingUpdateVersion = update.v
 		# We could use a global model for all docs, but we're hitting issues with the
 		# internal state of ShareJS not being accessible for clearing caches, and
 		# getting stuck due to queued callbacks (line 260 of sharejs/server/model.coffee)


use setTimeout instead of $timeout in pdf scrollhandler

--- services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee
+++ services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee
@@ -359,8 +359,8 @@
 						return
 					#scope.scrolled = true
 					if scope.scrollHandlerTimeout
-						$timeout.cancel(scope.scrollHandlerTimeout)
-					scope.scrollHandlerTimeout = $timeout scrollHandler, 25
+						clearTimeout(scope.scrollHandlerTimeout)
+					scope.scrollHandlerTimeout = setTimeout scrollHandler, 25

 				scrollHandler = () ->
 					renderVisiblePages()


Fix clock graph sort bug

Fix clock graph sort bug

--- plugins/clock/assets/clock/js/frontend.coffee
+++ plugins/clock/assets/clock/js/frontend.coffee
@@ -547,9 +547,9 @@
         name_and_times.times.push(start_stop)
         sorted_times.push(start_stop)

+    sorted_times = _.sortBy(sorted_times, (t) -> t.start)

     if @ignoreGaps
-      sorted_times = _.sortBy(sorted_times, (t) -> t.start)
       accumulated_gap = 0
       max_stop = 0
       for time,i in sorted_times
@@ -581,8 +581,8 @@

     @$(".time-block").each (i, el) ->
       $el = $(el)
-      start = parseInt($el.attr("data-start"))
-      end = parseInt($el.attr("data-stop"))
+      start = parseInt($el.attr("data-start"), 10)
+      end = parseInt($el.attr("data-stop"), 10)
       leftPercent = 100 * (start - startTime) / totalTime
       widthPercent = 100 * (end - start) / totalTime
       $(el).css({


Extra space

Extra space

--- desktop/apps/editorial_features/routes.coffee
+++ desktop/apps/editorial_features/routes.coffee
@@ -52,7 +52,7 @@
       res.locals.sd.IS_NESTED_PATH = slug?
       if res.locals.sd.IS_NESTED_PATH
         section = curation.get('sections')[videoIndex]
-        appendTitle = ' : ' + section.title
+        appendTitle = ': ' + section.title
         thumbnailImage = section.thumbnail_image
         url = sd.APP_URL + '/gender-equality/' + slug
         dateCreated = section.release_date


fixing join button to just go to /join, removed expand state

--- app/coffee/loginpanel.coffee
+++ app/coffee/loginpanel.coffee
@@ -14,17 +14,17 @@
       else
         $(this).parent().find('.loginPanel').slideUp()

-    $('.joinWrap a').click (event) ->
-      event.preventDefault()
-
-      $(this).parent().find('.join').hide()
-      $(this).parent().find('.joinButton').show()
-      $(this).parent().parent().find('.intro').slideUp()
-      $(this).parent().parent().find('.joinForm').slideDown()
-
-      $('.haveSeedcode').click =>
-        $('.haveSeedcode').slideUp('fast')
-        $('.seedcodeExpander').slideDown('fast')
+    # $('.joinWrap a').click (event) ->
+    #       event.preventDefault()
+    #
+    #       $(this).parent().find('.join').hide()
+    #       $(this).parent().find('.joinButton').show()
+    #       $(this).parent().parent().find('.intro').slideUp()
+    #       $(this).parent().parent().find('.joinForm').slideDown()
+    #
+    #       $('.haveSeedcode').click =>
+    #         $('.haveSeedcode').slideUp('fast')
+    #         $('.seedcodeExpander').slideDown('fast')

     # Check for cookie "welcome" if found, do nothing
     # if not found, display the welcomeWrap


Warn about unknown user in Result.upsert

--- server/models/result.coffee
+++ server/models/result.coffee
@@ -1,6 +1,7 @@
 mongoose = require('mongoose')

 import User from './user'
+import logger from '../log'

 resultsSchema = new mongoose.Schema
     _id: String
@@ -19,7 +20,11 @@

 resultsSchema.methods.upsert = () ->
     # required: user, table, total, solved, ok, attempts, ignored, lastSubmitId, lastSubmitTime
-    @userList = (await User.findById(@user)).userList
+    user = await User.findById(@user)
+    if not user
+        logger.warning "Unknown user #{@user} in Result.upsert, result id #{@_id}"
+        return
+    @userList = user.userList
     @_id = @user + "::" + @table
     @update(this, {upsert: true}).exec()


Update submit.coffee

Update submit.coffee

--- server/models/submit.coffee
+++ server/models/submit.coffee
@@ -55,6 +55,8 @@
     await @upsert()

 submitsSchema.methods.equivalent = (other) ->
+    if @user == "394891"
+        loger.log "Compare submits ", @this, other
     if @comments.length > 0
         return false
     if @outcome == "AC" or @outcome == "IG" or @outcome == "DQ"


cronを毎秒じゃなくて毎時に変更。

cronを毎秒じゃなくて毎時に変更。

--- scripts/cron.coffee
+++ scripts/cron.coffee
@@ -8,7 +8,7 @@

 module.exports = (robot) ->
   cronjob = new cronJob(
-    cronTime: '0 * * * * *'  # 毎分00秒
+    cronTime: '0 0 * * * *'     # 毎時00分00秒
     start:    true              # すぐにcronのjobを実行するか
     timeZone: 'Asia/Tokyo'      # タイムゾーン指定
     onTick: ->                  # 時間が来た時に実行する処理


Fix default profile data

Fix default profile data

--- www/coffee/services.coffee
+++ www/coffee/services.coffee
@@ -83,8 +83,7 @@
   @newProfile = () ->
     @profileData.lastId += 1
     newProfile = {
-      name: 'New Profile'
-      id: @profileData.lastId
+      id: @profileData.lastId ? 0
     }
     @putProfile newProfile
     newProfile
@@ -92,16 +91,8 @@
   @profileData = $localStorage.getObject 'profiles'
   if not @profileData?
     @profileData =
-      lastId: 1
-      profiles:
-        '0':
-          name: "Profile 1"
-          id: 0
-          location: 12
-        '1':
-          name: "Profile 2"
-          id: 1
-
+      lastId: 0
+      profiles: {}
     @persist @profileData

   null


More output.

More output.

--- src/coffee/pricesync.coffee
+++ src/coffee/pricesync.coffee
@@ -167,7 +167,7 @@
   _updatePrices: (retailerPrices, masterPrices, channelId, variantInMaster, retailerCustomerGroupId, masterCustomerGroupId) ->
     actions = []
     syncAmountOrCreate = (retailerPrice, masterPrice, priceType = 'normal') ->
-      console.error "Comparing %j", retailerPrice, masterPrices
+      console.error "Comparing %j", priceType, retailerPrice, masterPrice
       if masterPrice? and retailerPrice?
         if masterPrice.value.currencyCode isnt retailerPrice.value.currencyCode
           console.error "SKU #{variantInMaster.sku}: There are #{priceType} prices with different currencyCodes. R: #{retailerPrice.value.currencyCode} -> M: #{masterPrice.value.currencyCode}"
@@ -222,7 +222,7 @@

   _normalPrice: (prices) ->
     _.find prices, (p) ->
-      not _.has p, 'customerGroup'
+      not _.has(p, 'customerGroup')

   _salesPrice: (prices, customerGroupId) ->
     _.find prices, (p) ->


fixed module imports

fixed module imports

--- src/crystal/generate.coffee
+++ src/crystal/generate.coffee
@@ -130,8 +130,10 @@
 		# add module to loaded modules
 		loaded_modules[module_name][module_version] = module_config

-		# load submodules
-		if module_config.modules
+		# load submoduless
+		if module_config.imports
+			loadModules module_config.imports, module_config.host
+		else if module_config.modules
 			loadModules module_config.modules, module_config.host

 	loaded_modules = sortObject(loaded_modules)
@@ -143,6 +145,8 @@
 			loaded_module = module_versions[version_name]

 			submodules = {}
+			if loaded_module.imports
+				loaded_module.modules = loaded_module.imports
 			loaded_module.imports = {}
 			for submodule_name of loaded_module.modules
 				submodule_alias = submodule_name.substr(submodule_name.lastIndexOf('/') + 1)


Use config "options.directInput" as a {key (filename) : raw (API blueprint code)} source

--- test/unit/dredd-test.coffee
+++ test/unit/dredd-test.coffee
@@ -180,6 +180,78 @@
           assert.ok error
           done()

+    describe 'when configuration contains directInput object with "filename" as key, and an API Blueprint string as value', () ->
+      beforeEach ->
+        configuration =
+          server: 'http://localhost:3000/'
+          directInput: {
+            'direct': """
+              # API name
+
+              GET /url
+              + Response 200 (application/json)
+
+                      {"a":"b"}'
+              """
+          }
+          options:
+            silent: true
+        dredd = new Dredd(configuration)
+        sinon.stub dredd.runner, 'executeTransaction', (transaction, callback) ->
+          callback()
+
+      afterEach () ->
+        dredd.runner.executeTransaction.restore()
+
+      it 'should not expand any glob patterns', (done) ->
+        dredd.run (error) ->
+          return done error if error
+          assert.lengthOf dredd.configuration.files, 0
+          done()
+
+      it 'should pass data contents to config', (done) ->
+        dredd.run (error) ->
+          return done error if error
+          assert.isObject dredd.configuration.data
+          assert.deepPropertyVal dredd, 'configuration.data.direct.filename', 'direct'
+          assert.deepProperty    dredd, 'configuration.data.direct.raw'
+          done()
+
+      it 'should parse passed data contents', (done) ->
+        dredd.run (error) ->
+          return done error if error
+          assert.deepProperty dredd, 'configuration.data.direct.parsed'
+          done()
+
+      describe 'and I also set configuration.options.path to an existing file', ->
+        localdredd = null
+        beforeEach ->
+          configuration.options ?= {}
+          configuration.options.path = ['./test/fixtures/apiary.apib']
+          localdredd = new Dredd(configuration)
+          sinon.stub localdredd.runner, 'executeTransaction', (transaction, callback) ->
+            callback()
+
+        afterEach ->
+          localdredd.runner.executeTransaction.restore()
+
+        it 'should fill configuration data with directInput and one file at that path', (done) ->
+          localdredd.run (error) ->
+            return done error if error
+            assert.lengthOf    localdredd.configuration.files, 1
+            assert.isObject    localdredd.configuration.data
+            assert.lengthOf    Object.keys(localdredd.configuration.data), 2
+            assert.property    localdredd.configuration.data, './test/fixtures/apiary.apib'
+            assert.propertyVal localdredd.configuration.data['./test/fixtures/apiary.apib'], 'filename', './test/fixtures/apiary.apib'
+            assert.property    localdredd.configuration.data['./test/fixtures/apiary.apib'], 'raw'
+            assert.property    localdredd.configuration.data['./test/fixtures/apiary.apib'], 'parsed'
+            assert.deepPropertyVal localdredd, 'configuration.data.direct.filename', 'direct'
+            assert.deepProperty    localdredd, 'configuration.data.direct.raw'
+            assert.deepProperty    localdredd, 'configuration.data.direct.parsed'
+            done()
+
+
+
   describe 'when Blueprint parsing error', () ->

     before () ->


updated keycodes for presentation remotes

--- lib/assets/javascripts/attentive/presentation.js.coffee
+++ lib/assets/javascripts/attentive/presentation.js.coffee
@@ -74,9 +74,9 @@
     switch e.keyCode
       when 72
         this.advanceTo(0)
-      when 37
+      when 37, 33
         this.advance(-1)
-      when 39, 32
+      when 39, 32, 34
         this.advance()
       when 220
         @timer.reset()


increased relay token timeout

increased relay token timeout

--- tests/specs/05.relay.coffee
+++ tests/specs/05.relay.coffee
@@ -66,7 +66,7 @@

   it 'emits token timeout event', (done)->
     rt = Config.RELAY_TOKEN_TIMEOUT
-    Config.RELAY_TOKEN_TIMEOUT = 1
+    Config.RELAY_TOKEN_TIMEOUT = 10
     r = new Relay(__globalTest.host)
     r.on 'relaytokentimeout', ->
       Config.RELAY_TOKEN_TIMEOUT = rt


Tests:IDE:Layout: Added openDrawingBoard test.

--- tests/src/ide/layout.coffee
+++ tests/src/ide/layout.coffee
@@ -71,3 +71,18 @@
       .click                     '.application-tab-handle-holder .plus'
       .waitForElementNotPresent  '.context-list-wrapper li.undo-split', 20000 # Assertion
       .end()
+
+
+  openDrawingBoard: (browser) ->
+
+    helpers.beginTest(browser)
+    helpers.waitForVMRunning(browser)
+
+    browser
+      .waitForElementVisible   '.application-tab-handle-holder', 20000
+      .click                   '.application-tab-handle-holder .plus'
+      .waitForElementVisible   '.context-list-wrapper', 20000
+      .click                   '.context-list-wrapper li.new-drawing-board'
+      .pause                   2000
+      .waitForElementVisible   '.drawing-pane .drawing-board-toolbar', 20000 # Assertion
+      .end()


JDomain: Update regular expressions

JDomain: Update regular expressions

--- workers/social/lib/social/models/domain.coffee
+++ workers/social/lib/social/models/domain.coffee
@@ -153,10 +153,9 @@
       {domain} = domain
       return yes  unless /\.kd\.io$/.test domain

-      re = if group is "koding"
-             new RegExp(account.profile.nickname + '\.kd\.io$')
-           else
-             new RegExp('(.*)\.' + group + '\.kd\.io$')
+      re = if group is "koding" \
+           then ///#{account.profile.nickname}\.kd\.io$///
+           else ///(.*)\.#{group}\.kd\.io$///

       isVmAlias         = (/^shared|vm[\-]?([0-9]+)?/.test domain)
       isKodingSubdomain = (/(.*)\.(koding|guests)\.kd\.io$/.test domain)
@@ -180,18 +179,8 @@
       err: new KodingError message, "INVALIDDOMAIN"

     # Domain check ~
-    # ^                          start of the line
-    #   [A-Za-z0-9-]+            start with the string in the brackets [ ], must contain one or more (+)
-    #       (                    start of group #1 - For sub-domain.
-    #        \\.[A-Za-z0-9-]+    follow by a dot "." and string in the brackets [ ], must contain one or more (+)
-    #       )*                   end of group #1, this group is optional (*)
-    #       (                    start of group #2 - check the extension
-    #        \\.[A-Za-z]{2,}     follow by a dot "." and string in the brackets [ ], with minimum length of 2
-    #       )                    end of group #2
-    # $                          end of the line
-
     return err()  unless \
-      /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/i.test domain
+      /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}$/i.test domain

     # Return domain type as custom and keep the domain as is
     return {type: 'custom', domain}  unless /\.kd\.io$/.test domain


add company_id

add company_id

--- angular/core/services/intercom_service.coffee
+++ angular/core/services/intercom_service.coffee
@@ -3,6 +3,7 @@
   mapGroup = (group) ->
     return null unless group?
     id: group.id
+    company_id: group.id
     key: group.key
     name: group.name
     description: group.description.substring(0, 250)


Improve functionality

Improve functionality

--- app/assets/javascripts/LabelManager.js.coffee
+++ app/assets/javascripts/LabelManager.js.coffee
@@ -1,4 +1,6 @@
 class @LabelManager
+  errorMessage: 'Unable to update label prioritization at this time'
+
   constructor: (opts = {}) ->
     # Defaults
     {
@@ -27,7 +29,7 @@
     action = if $btn.parents('.js-prioritized-labels').length then 'remove' else 'add'
     _this.toggleLabelPriority($label, action)

-  toggleLabelPriority: ($label, action, persistState = false) ->
+  toggleLabelPriority: ($label, action, persistState = true) ->
     _this = @
     url = $label.find('.js-toggle-priority').data 'url'

@@ -48,31 +50,32 @@
     $label.detach().appendTo($target)

     # Return if we are not persisting state
-    return if persistState
+    return unless persistState

     if action is 'remove'
       xhr = $.ajax url: url, type: 'DELETE'
+    else
+      xhr = @savePrioritySort($label, action)

-      # If request fails, put label back to Other labels group
-      xhr.fail ->
-        _this.toggleLabelPriority($label, 'remove', true)
-
-        # Show a message
-        new Flash('Unable to update label prioritization at this time' , 'alert')
-    else
-      @savePrioritySort()
+    xhr.fail @rollbackLabelPosition.bind(@, $label, action)

   onPrioritySortUpdate: ->
-    @savePrioritySort()
-
-  savePrioritySort: ->
-    xhr = $.post
-            url: @prioritizedLabels.data('url')
-            data:
-              label_ids: @getSortedLabelsIds()
+    xhr = @savePrioritySort()

     xhr.fail ->
-      new Flash('Unable to update label prioritization at this time' , 'alert')
+      new Flash(@errorMessage, 'alert')
+
+  savePrioritySort: () ->
+    $.post
+      url: @prioritizedLabels.data('url')
+      data:
+        label_ids: @getSortedLabelsIds()
+
+  rollbackLabelPosition: ($label, originalAction)->
+    action = if originalAction is 'remove' then 'add' else 'remove'
+    @toggleLabelPriority($label, action, false)
+
+    new Flash(@errorMessage, 'alert')

   getSortedLabelsIds: ->
     sortedIds = []


Increase number of y-ticks on HHP COP chart

--- app/assets/javascripts/d3/hhp_cop_cost.coffee
+++ app/assets/javascripts/d3/hhp_cop_cost.coffee
@@ -168,7 +168,7 @@
     createYAxis: (scale) ->
       d3.svg.axis().scale(scale)
         .orient('left')
-        .ticks(4)
+        .ticks(6)
         .tickSize(-@width, 0)
         .tickFormat((v) => v)


deleted unused functions

deleted unused functions

--- app/assets/javascripts/pirates/game.js.coffee
+++ app/assets/javascripts/pirates/game.js.coffee
@@ -48,21 +48,6 @@
   $("#runBtn").click () ->
     webSocket.trigger "code", {code: window.codeMirror.getValue()}

-  injectShipFunctions = (code) ->
-    "def move\n
-      `window.ship.move()`\n
-    end\n
-    def turnLeft\n
-      `window.ship.rotateLeft()`\n
-    end\n
-    def turnRight\n
-      `window.ship.rotateRight()`\n
-    end\n
-    def monsterInFront\n
-      `window.ship.monsterInFront()`\n
-    end\n
-    #{ code }"
-
   ###
     Main Loop
   ###


clickable variables done for now.
closes #865

yet there is still issue #874

--- app/assets/javascripts/pirates/game.js.coffee
+++ app/assets/javascripts/pirates/game.js.coffee
@@ -99,7 +99,7 @@
         hoveringSelection = $ "
#{selection}
"

         dropdownToggle = $ '#watchlist-dropdown'
-        $(hoveringSelection).css({
+        hoveringSelection.css({
           position: 'absolute'
           top:  window.mouse.y
           left: window.mouse.x


Fix Movie#isPaused

Fix Movie#isPaused

--- app/assets/javascripts/player/movie.js.coffee
+++ app/assets/javascripts/player/movie.js.coffee
@@ -85,7 +85,7 @@
     @playing

   isPaused: ->
-    !@isPlaying() and !@isFinished()
+    !@isPlaying() and !@isFinished() and @frameNo > 0

   isFinished: ->
     !@isPlaying() and @isLoaded() and @frameNo >= @timing().length


Js for cart page, more flexibe

Js for cart page, more flexibe

--- app/assets/javascripts/store/script.js.coffee
+++ app/assets/javascripts/store/script.js.coffee
@@ -15,4 +15,17 @@

     # Activate already checked payment method if form is re-rendered
     # i.e. if user enters invalid data
-    ($ 'input[type="radio"]:checked').click()+    ($ 'input[type="radio"]:checked').click()
+
+    ($ 'input#order_use_billing').click(->
+      if ($ this).is(':checked')
+        ($ 'input[type="submit"][value="Checkout"][data-hook="one_page_checout_button"]').css("margin-left", "10px")
+        ($ '#shipping_method_wrapper').removeClass('alpha')
+        ($ '#shipping_method_wrapper').addClass('omega')
+      else
+        ($ 'input[type="submit"][value="Checkout"][data-hook="one_page_checout_button"]').css("margin-left", "0")
+        ($ '#shipping_method_wrapper').removeClass('omega')
+        ($ '#shipping_method_wrapper').addClass('alpha')
+    ).triggerHandler 'click'
+    # deface cannot did it
+    ($ 'button#checkout-link').remove()


Fixes issue in #91 where current section would be lost on form submit

--- app/assets/javascripts/housing_forms.js.coffee
+++ app/assets/javascripts/housing_forms.js.coffee
@@ -14,7 +14,7 @@
       else
         section.toggleClass 'hide', true
     $('.wizard-nav a').each ()->
-      link = $ this
+      link = $ @
       parent = link.parent()
       if link.attr('href') is hash
         parent.toggleClass 'active', true
@@ -22,9 +22,13 @@
         parent.toggleClass 'active', false

   $(window).on 'hashchange', changeSection
-
-  firstSectionHash = $('.wizard-nav a').eq(0).attr 'href'
-  if not window.location.hash.length
-    window.location.hash = firstSectionHash
-  else
-    changeSection()
+
+  initialize = ->
+    firstSectionHash = $('.wizard-nav a').eq(0).attr 'href'
+    if not window.location.hash.length
+      window.location.hash = firstSectionHash
+    else
+      changeSection()
+
+  $(document).ajaxComplete initialize
+  initialize()


camel case fixing [af14ceaca7ceda7c1e698196bca1d76ec9862e0e]

--- app/assets/javascripts/models/commit.js.coffee
+++ app/assets/javascripts/models/commit.js.coffee
@@ -4,7 +4,7 @@
   state: DS.attr('string')
   remoteUrl: DS.attr('string')
   project: DS.belongsTo('Review.Project')
-  expires_at: DS.attr('date')
+  expiresAt: DS.attr('date')
   createdAt: DS.attr('date')
   authoredAt: DS.attr('date')
   author: DS.belongsTo('Review.Author')


brief pause

brief pause

--- app/assets/javascripts/smithy/assets.js.coffee
+++ app/assets/javascripts/smithy/assets.js.coffee
@@ -26,7 +26,10 @@
       to = $('#fileupload').data('post') + ".js"
       content = {}
       content[$('#fileupload').data('as')] = domain + path
-      $.post(to, content)
+      setTimeout ->
+        $.post(to, content)
+      , 1500
+

       data.context.remove() if data.context # remove progress bar


Remove Test Button

Remove Test Button

--- app/classifier/tasks/drawing/grid-buttons.cjsx
+++ app/classifier/tasks/drawing/grid-buttons.cjsx
@@ -59,11 +59,6 @@
         pref.update 'preferences.grid': null
         @activateTemplate null
         @setState hideDrawingTools: false
-      pref.save()
-
-  terminate: ->
-    @props.user.get('project_preferences', {project_id: @props.workflow.links.project}).then ([pref]) =>
-      pref.update 'preferences': {}
       pref.save()

   saveRow: (marks) ->
@@ -178,11 +173,6 @@
                   clear
                 </button>
               </td>
-              <td>
-                <button type="button" className="grid-button-template" onClick={@terminate.bind this, null}>
-                  Terminate!
-                </button>
-              </td>
             </tr>

           </tbody>


Remove unused short property names from AnalyticsLogEvent schema

In 2015, we were going to switch to u, e, p from user, event,
properties, and we started tracking some events both ways for a while
in preparation for switching, but then we never finished
migrating. Then, in 2017, we refactored the server and it stopped
storing the shortened event names anyway. We don't have events
currently from before 2018, so don't think we need this confusion in
the schema any more.

To shorten? No, don't want to have to deal with migrating data, and
MongoDB has long since gotten its compression on field names pretty
good, obviating the need for manual optimization to short field names.


Force bitcoin ws network

Force bitcoin ws network

--- app/src/tasks/transaction_observer_task.coffee
+++ app/src/tasks/transaction_observer_task.coffee
@@ -11,8 +11,8 @@
   _listenNewTransactions: () ->
     @newTransactionStream = new WebSocket "wss://ws.chain.com/v2/notifications"
     @newTransactionStream.onopen = () =>
-      @newTransactionStream.send JSON.stringify type: "new-transaction", block_chain: ledger.config.network.ws_chain
-      @newTransactionStream.send JSON.stringify type: "new-block", block_chain: ledger.config.network.ws_chain
+      @newTransactionStream.send JSON.stringify type: "new-transaction", block_chain: "bitcoin"
+      @newTransactionStream.send JSON.stringify type: "new-block", block_chain: "bitcoin"

     @newTransactionStream.onmessage = (event) =>
       data = JSON.parse(event.data)


Use event.clientX when available in Resizer#onDragEnd

ref #265

--- assets/javascripts/views/layout/resizer.coffee
+++ assets/javascripts/views/layout/resizer.coffee
@@ -45,5 +45,5 @@
     return

   onDragEnd: (event) =>
-    @resize(event.screenX - window.screenX, true)
+    @resize(event.clientX or (event.screenX - window.screenX), true)
     return


Don't set/warn width/height in afterRender

--- src/svgtiler.coffee
+++ src/svgtiler.coffee
@@ -633,17 +633,18 @@
       ## svgBBox) or changed to avoid zeroes.
       @dom.documentElement.setAttribute 'viewBox', @viewBox.join ' '
     @overflowBox = extractOverflowBox @dom
-    @width = forceWidth if (forceWidth = @getSetting 'forceWidth')?
-    @height = forceHeight if (forceHeight = @getSetting 'forceHeight')?
-    warnings = []
-    unless @width?
-      warnings.push 'width'
-      @width = 0
-    unless @height?
-      warnings.push 'height'
-      @height = 0
-    if warnings.length > 0
-      console.warn "Failed to detect #{warnings.join ' and '} of SVG for tile '#{@key}'"
+    if wrapper == 'symbol'
+      @width = forceWidth if (forceWidth = @getSetting 'forceWidth')?
+      @height = forceHeight if (forceHeight = @getSetting 'forceHeight')?
+      warnings = []
+      unless @width?
+        warnings.push 'width'
+        @width = 0
+      unless @height?
+        warnings.push 'height'
+        @height = 0
+      if warnings.length > 0
+        console.warn "Failed to detect #{warnings.join ' and '} of SVG for tile '#{@key}'"
     ## Detect special `width="auto"` and/or `height="auto"` fields for future
     ## processing, and remove them to ensure valid SVG.
     @autoWidth = isAuto @dom, 'width'


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -11,7 +11,7 @@

   window.keydown = {}
-  keydown.left = true
+  window.keydown.left = true

   player.update()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -85,7 +85,7 @@

   player.update()

-  e
+  equals player.

 test "should move player according to their speed", ->
   ;


Added a couple assert descriptions

Added a couple assert descriptions

--- test/deps/install.coffee
+++ test/deps/install.coffee
@@ -32,9 +32,10 @@
       installNodeDev stub, (err) ->
         should.not.exist err
         fs.readdir path.join(stub, 'node_modules'), (err, files) ->
-          should.not.exist err
-          console.log 'Holy shit files', files
-          files.should.have.length 1
+          should.not.exist err,
+            'Reading node_modules returned an error. Does it exist?'
+          files.should.includeEql 'example',
+            'The `example` package was not installed.'
           done()

   describe 'on stubs/proddeps', ->
@@ -44,9 +45,10 @@
       installNodeDev stub, (err) ->
         should.not.exist err
         fs.readdir path.join(stub, 'node_modules'), (err, files) ->
-          should.not.exist err
-          console.log 'Holy shit files', files
-          files.should.have.length 1
+          should.not.exist err,
+            'Reading node_modules returned an error. Does it exist?'
+          files.should.includeEql 'example',
+            'The `example` package was not installed.'
           done()


Retry-on-error for favorite bus lines

Retry-on-error for favorite bus lines

--- cs/options.coffee
+++ cs/options.coffee
@@ -220,15 +220,22 @@

   # Get and inject possible lines for correct stop
   busStopId = Bus.getStop stopName, direction
+
   Bus.getLines busStopId, (json) ->
-
-    # Is result an error message?
-    if typeof json is 'string'
-      $(cssSelector + ' .lines').html ''+json+''
+    # Did the json even reach us? Is the result an error message?
+    if typeof json is 'undefined' or typeof json is 'string'
+      errorMessage = (typeof json is 'undefined' ? 'Oops, noe gikk galt' : json)
+      $(cssSelector + ' .lines').html 'Oops, noe gikk galt'
+      setTimeout ( ->
+        $(cssSelector + ' .lines').html 'Prøve igjen?'
+        $(cssSelector + ' .lines .retry').click ->
+          getFavoriteLines busField
+      ), 2500
     else
       # Sort lines and remove duplicates
       arrayOfLines = []
-      for item in json.lines
+      # for item in json.lines # this is probably more correct to use for the future
+      for item in json.next
         if -1 is arrayOfLines.indexOf Number item.line
           # Casting strings to numbers to make them easily sortable
           arrayOfLines.push Number item.line


options: showing debug links again, missed them <3

--- cs/options.coffee
+++ cs/options.coffee
@@ -517,7 +517,7 @@
 # Document ready, go!
 $ ->
   if DEBUG
-    # $('#debug_links').show()
+    $('#debug_links').show()
     $('button.debug').click ->
       Browser.openTab $(this).attr 'data'


Remove unused repo variable

Remove unused repo variable

--- spec/app/editor-spec.coffee
+++ spec/app/editor-spec.coffee
@@ -2204,7 +2204,7 @@
       expect(editSession.save).toHaveBeenCalled()

   describe ".checkoutHead()", ->
-    [repo, path, originalPathText] = []
+    [path, originalPathText] = []

     beforeEach ->
       path = require.resolve('fixtures/git/working-dir/file.txt')


Fix bug where coffeescript would only execute after page refresh.

--- BHCDatabase/app/assets/javascripts/users.coffee
+++ BHCDatabase/app/assets/javascripts/users.coffee
@@ -2,25 +2,28 @@
 # All this logic will automatically be available in application.js.
 # You can use CoffeeScript in this file: http://coffeescript.org/

-window.onload = ->
-  btn = undefined
-  modal = undefined
-  span = undefined
-  modal = document.getElementById('modalcontainer')
-  btn = document.getElementById('openmodal')
-  span = document.getElementsByClassName('close')[0]
+ready = ->
+    btn = undefined
+    modal = undefined
+    span = undefined
+    modal = document.getElementById('modalcontainer')
+    btn = document.getElementById('openmodal')
+    span = document.getElementsByClassName('close')[0]

-  btn.onclick = ->
-    modal.style.display = 'block'
-    return
+    btn.onclick = ->
+      modal.style.display = 'block'
+      return

-  span.onclick = ->
-    modal.style.display = 'none'
-    return
+    span.onclick = ->
+      modal.style.display = 'none'
+      return

-  window.onclick = (event) ->
-    if event.target == modal
-      modal.style.display = 'none'
-    return
+    window.onclick = (event) ->
+      if event.target == modal
+        modal.style.display = 'none'
+      return

-  return
+
+  $(document).ready(ready)
+  $(document).on('turbolinks:load', ready)
+  $(document).on('page:load', ready)


fix verbose behavior

fix verbose behavior

--- src/s3.coffee
+++ src/s3.coffee
@@ -6,6 +6,7 @@
 class MyS3
   constructor: (options) ->
     options.apiVersion = '2006-03-01'
+    @_verbose = options.verbose ? false
     @_client = new S3 options

   listAllObjects: (options, result = []) ->
@@ -21,7 +22,7 @@
     files.reduce (promise, { key, path }) =>
       promise
       .then =>
-        console.log("upload #{path} to #{Bucket}/#{key}") if verbose
+        console.log("upload #{path} to #{Bucket}/#{key}") if @_verbose
         @_putObject
           Bucket: Bucket
           Key: key


sort method

sort method

--- src/s3.coffee
+++ src/s3.coffee
@@ -28,17 +28,17 @@
           ContentType: mime.lookup path
     , Promise.resolve()

+  _listObjects: (options) ->
+    new Promise (resolve, reject) =>
+      @_client.listObjects options, (err, data) ->
+        return reject(err) if err?
+        resolve data
+
   _putObject: (options) ->
     new Promise (resolve, reject) =>
       @_client.putObject options, (err) ->
         return reject(err) if err?
         resolve()

-  _listObjects: (options) ->
-    new Promise (resolve, reject) =>
-      @_client.listObjects options, (err, data) ->
-        return reject(err) if err?
-        resolve data
-
 module.exports = (options) ->
   new MyS3 options


Add missing import

Add missing import

--- resources/assets/coffee/react/profile-page/links.coffee
+++ resources/assets/coffee/react/profile-page/links.coffee
@@ -16,7 +16,7 @@
 #    along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
 ###

-{div, span} = ReactDOMFactories
+{a, div, span} = ReactDOMFactories
 el = React.createElement


Display connection message

Display connection message

--- lib/js/integrations/slack_integration.coffee
+++ lib/js/integrations/slack_integration.coffee
@@ -31,7 +31,7 @@
       @id = @slack.self.id
       @steam = new Steam(slackTeam: @id)
       @slack_channels = (channel for id, channel of @slack.channels when channel.is_member)
-      #@sendMessage("I'm live! Running version #{pkg.version}", @slack_channels[0])
+      @sendMessage("I'm live! Running version #{pkg.version}", @slack_channels[0])

     @slack.on 'message', (message)=>
       channel = @slack.getChannelGroupOrDMByID(message.channel)


Cleanup show answer code

Cleanup show answer code

--- lms/static/coffee/src/modules/problem.coffee
+++ lms/static/coffee/src/modules/problem.coffee
@@ -45,17 +45,14 @@
         $.each response, (key, value) =>
           if $.isArray(value)
             for choice in value
-              @$("label[for='input_#{key}_#{choice}']").attr
-                correct_answer: 'true'
+              @$("label[for='input_#{key}_#{choice}']").attr correct_answer: 'true'
           else
-            @$("#answer_#{key}").html(value)	# needs to be html, not text, for complex solutions (eg coding)
-            @$("#solution_#{key}").html(value)	# needs to be html, not text, for complex solutions (eg coding)
+            @$("#answer_#{key}, #solution_#{key}").html(value)
         MathJax.Hub.Queue ["Typeset", MathJax.Hub]
         @$('.show').val 'Hide Answer'
         @element.addClass 'showed'
     else
-      @$('[id^=answer_]').text ''
-      @$('[id^=solution_]').text ''
+      @$('[id^=answer_], [id^=solution_]').text ''
       @$('[correct_answer]').attr correct_answer: null
       @element.removeClass 'showed'
       @$('.show').val 'Show Answer'


need jscocoa in fs.coffee

need jscocoa in fs.coffee

--- src/fs.coffee
+++ src/fs.coffee
@@ -2,6 +2,8 @@
 # http://ringojs.org/api/v0.8/fs/

 _ = require 'underscore'
+
+jscocoa = require 'jscocoa'

 module.exports =
   # Make the given path absolute by resolving it against the


JDomain: returning 2 parameters to avoid warning

--- workers/social/lib/social/models/domain.coffee
+++ workers/social/lib/social/models/domain.coffee
@@ -331,12 +331,12 @@
   bindVM: (client, params, callback)->
     domainName = @domain
     operation  = {'$addToSet': hostnameAlias: params.hostnameAlias}
-    JDomain.update {domain:domainName}, operation, callback
+    JDomain.update {domain:domainName}, operation, (err) -> callback err

   unbindVM: (client, params, callback)->
     domainName = @domain
     operation  = {'$pull': hostnameAlias: params.hostnameAlias}
-    JDomain.update {domain:domainName}, operation, callback
+    JDomain.update {domain:domainName}, operation, (err) -> callback err

   bindVM$: permit
     advanced: [


Fix parameter handling

Fix parameter handling

--- web/app/models/tweets.coffee
+++ web/app/models/tweets.coffee
@@ -58,10 +58,14 @@
 		listed_weight: parseFloat(listedWeight)
 	}

-	params.retweet_weight = 0.3 if not params.retweet_weight?
-	params.favorites_weight = 0.3 if not params.favorites_weight?
-	params.followers_weight = 0.3 if not params.followers_weight?
-	params.listed_weight = 0.1 if not params.listed_weight?
+	console.log(params)
+
+	params.retweet_weight = 0.3 if not params.retweet_weight? || isNaN(params.retweet_weight)
+	params.favorites_weight = 0.3 if not params.favorites_weight? || isNaN(params.favorites_weight)
+	params.followers_weight = 0.3 if not params.followers_weight? || isNaN(params.followers_weight)
+	params.listed_weight = 0.1 if not params.listed_weight? || isNaN(params.listed_weight)
+
+	console.log(params)

 	neodb.query(query, params, callback)


load inspect_commands

load inspect_commands

--- src/layout/inspector.coffee
+++ src/layout/inspector.coffee
@@ -1,13 +1,14 @@
 {my} = require '../my'
 {vector} = require '../god/vector'
 {inspect_status} = require './inspect_status'
+{inspect_commands} = require './inspect_commands'

 sprite_inspector = (sprite) ->
   {
     _LABEL: "inspector_#{sprite.get 'name'}"
     _CHILDREN: [
       inspect_status(sprite)
-      "commands"
+      inspect_commands(sprite)
       "behavior"
     ]
   }


GoogleFriendlyKoding: Changed fallback URL in profile.

--- server/lib/crawler/staticpages/profile.coffee
+++ server/lib/crawler/staticpages/profile.coffee
@@ -22,7 +22,7 @@
   commentsList = ""
   if statusUpdate?.replies
     for comment in statusUpdate.replies
-      avatarUrl = "https://gravatar.com/avatar/#{comment.author.hash}?size=90&d=mm"
+      avatarUrl = "https://gravatar.com/avatar/#{comment.author.hash}?size=90&d=https://koding-cdn.s3.amazonaws.com/images/default.avatar.140.png&r=g"
       commentsList +=
         """
           <div class="kdview kdlistitemview kdlistitemview-comment">


Sitemap: Change sUpdates parameter name to statusUpdates

--- server/lib/crawler/staticpages/profile.coffee
+++ server/lib/crawler/staticpages/profile.coffee
@@ -22,11 +22,11 @@

   """

-putContent = (account, sUpdates)=>
+putContent = (account, statusUpdates)=>
   profile      = getProfile account

-  if sUpdates is ""
-    sUpdates = """
#{profile.fullName} has not shared any posts yet.
"""
+  if statusUpdates is ""
+    statusUpdates = """
#{profile.fullName} has not shared any posts yet.
"""

   numberOfLikes     = if account?.counts?.likes     then account.counts.likes     else "0"
   numberOfFollowers = if account?.counts?.followers then account.counts.followers else "0"
@@ -72,7 +72,7 @@

-                        #{sUpdates}
+                        #{statusUpdates}


Add commented out docker config

Add commented out docker config

--- services/clsi/config/settings.defaults.coffee
+++ services/clsi/config/settings.defaults.coffee
@@ -17,6 +17,17 @@
 		clsiCacheDir: Path.resolve(__dirname + "/../cache")
 		synctexBaseDir: (project_id) -> Path.join(@compilesDir, project_id)

+	# clsi:
+	# 	commandRunner: "docker-runner-sharelatex"
+	# 	docker:
+	# 		image: "quay.io/sharelatex/texlive-full"
+	# 		env:
+	# 			PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/texlive/2013/bin/x86_64-linux/"
+	# 			HOME: "/tmp"
+	# 		modem:
+	# 			socketPath: false
+	# 		user: "tex"
+
 	internal:
 		clsi:
 			port: 3013


add unique index to both token fields

add unique index to both token fields

--- services/web/app/coffee/models/Project.coffee
+++ services/web/app/coffee/models/Project.coffee
@@ -33,8 +33,8 @@
 	imageName         : { type: String }
 	track_changes     : { type: Object }
 	tokens            :
-		readOnly        : { type: String }
-		readAndWrite    : { type: String }
+		readOnly        : { type: String, index: {unique: true} }
+		readAndWrite    : { type: String, index: {unique: true} }
 	tokenAccessReadOnly_refs         : [ type:ObjectId, ref:'User' ]
 	tokenAccessReadAndWrite_refs     : [ type:ObjectId, ref:'User' ]
 	overleaf          :


JSTableView update

JSTableView update

--- JSKit/04_JSTableView.coffee
+++ JSKit/04_JSTableView.coffee
@@ -44,7 +44,7 @@
 		dispNum = parseInt(bounds.size.height / @_rowHeight)

 		# 各セルの内容を返すデリゲートメソッドを呼ぶ
-		diff_y = 24
+		diff_y = 32
 		for i in [0...@_dataNum]
 			cell = @dataSource.cellForRowAtIndexPath(i)
 			cell._cellnum = i
@@ -83,13 +83,12 @@

 	viewDidAppear:->
 		super()
-		JSLog("tableView=%@, titlebar=%@", @_tableView, @titlebar)
 		if (!@_tableView?)
 			@_tableView = new JSScrollView()
 			@_self.addSubview(@_tableView)
 		if (!@titleBar?)
 			bounds = getBounds()
-			@titleBar = new JSLabel(JSRectMake(0, 0, bounds.size.width, 24))
+			@titleBar = new JSLabel(JSRectMake(0, 0, bounds.size.width, 32))
 			@titleBar.setAlpha(0.9)
 			@_self.addSubview(@titleBar)
 		@addTableView()


ComputeController: handle timedOut errors correctly, and cancel them when needed.

--- client/Main/providers/computecontroller.coffee
+++ client/Main/providers/computecontroller.coffee
@@ -140,7 +140,7 @@
       @emit "renderStacks"

-  errorHandler = (task, eventListener, machine)->
+  errorHandler: (call, task, machine)->

     ComputeErrors = {
       "TimeoutError", "KiteError", Pending: "107"
@@ -157,15 +157,16 @@
         KD.utils.wait timeout, ->
           KD.singletons.computeController[task] machine

-    (err)->
-
-      eventListener.revertToPreviousState machine
+    (err)=>
+
+      @eventListener.revertToPreviousState machine

       switch err.name

         when ComputeErrors.TimeoutError

           retryIfNeeded task, machine
+          call.cancel()

         when ComputeErrors.KiteError

@@ -173,10 +174,9 @@
             if err.code is ComputeErrors.Pending
               retryIfNeeded task, machine
             else
-              eventListener.triggerState machine, status: Machine.State.Unknown
-
-
-      warn "info err:", err
+              @eventListener.triggerState machine, status: Machine.State.Unknown
+
+      warn "info err:", err, this

   destroy: (machine)->
@@ -187,16 +187,16 @@
         status      : Machine.State.Terminating
         percentage  : 0

-      @kloud.destroy { machineId: machine._id }
+      call = @kloud.destroy { machineId: machine._id }
+
+      call.timeout ComputeController.timeout

       .then (res)=>

         @eventListener.addListener 'destroy', machine._id
         log "destroy res:", res

-      .timeout ComputeController.timeout
-
-      .catch errorHandler 'destroy', @eventListener, machine
+      .catch @errorHandler call, 'destroy', machine

   build: (machine)->
@@ -207,16 +207,16 @@

     machine.getBaseKite().disconnect()

-    @kloud.build { machineId: machine._id }
+    call = @kloud.build { machineId: machine._id }
+
+    call.timeout ComputeController.timeout

     .then (res)=>

       @eventListener.addListener 'build', machine._id
       log "build res:", res

-    .timeout ComputeController.timeout
-
-    .catch errorHandler 'build', @eventListener, machine
+    .catch @errorHandler call, 'build', machine

   start: (machine)->
@@ -225,16 +225,16 @@
       status      : Machine.State.Starting
       percentage  : 0

-    @kloud.start { machineId: machine._id }
+    call = @kloud.start { machineId: machine._id }
+
+    call.timeout ComputeController.timeout

     .then (res)=>

       @eventListener.addListener 'start', machine._id
       log "start res:", res

-    .timeout ComputeController.timeout
-
-    .catch errorHandler 'start', @eventListener, machine
+    .catch @errorHandler call, 'start', machine

   stop: (machine)->
@@ -245,16 +245,16 @@

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

-    @kloud.stop { machineId: machine._id }
+    call = @kloud.stop { machineId: machine._id }
+
+    call.timeout ComputeController.timeout

     .then (res)=>

       @eventListener.addListener 'stop', machine._id
       log "stop res:", res

-    .timeout ComputeController.timeout
-
-    .catch errorHandler 'stop', @eventListener, machine
+    .catch @errorHandler call, 'stop', machine

   StateEventMap =
@@ -277,7 +277,9 @@
       status      : machine.status.state
       percentage  : 0

-    @kloud.info { machineId: machine._id }
+    call = @kloud.info { machineId: machine._id }
+
+    call.timeout ComputeController.timeout

     .then (response)=>

@@ -286,11 +288,7 @@
         status      : response.state
         percentage  : 100

-    .timeout ComputeController.timeout
-
-    .catch errorHandler 'info', @eventListener, machine
-
-
+    .catch @errorHandler call, 'info', machine

   requireMachine: (options = {}, callback = noop)-> @ready =>


Use applications kite for installing app

--- client/app/MainApp/kodingappscontroller.coffee
+++ client/app/MainApp/kodingappscontroller.coffee
@@ -523,6 +523,7 @@
                 callback? err
               else
                 options =
+                  kiteName      : "applications"
                   method        : "installApp"
                   withArgs      :
                     owner       : acc.profile.nickname


Client: Sidebar: Added getRequiredInvitationMachineId method to make sure which invitationWidget will show

--- client/app/lib/components/sidebar/index.coffee
+++ client/app/lib/components/sidebar/index.coffee
@@ -52,6 +52,19 @@

     EnvironmentFlux.actions.setActiveInvitationMachineId id  if id

+
+  getRequiredInvitationMachineId: ->
+
+    machineId = null
+    (@state.sharedMachines.concat @state.collaborationMachines).forEach (machine) ->
+
+      return  if machineId
+      return  if machine.get('type') is 'own'
+      return  if machine.get('isApproved')
+
+      machineId =  machine.get '_id'
+
+    return machineId

   renderInvitationWidget: ->


Environment actions: remove useless DELETE_STACK action call

--- client/app/lib/flux/environment/actions.coffee
+++ client/app/lib/flux/environment/actions.coffee
@@ -523,7 +523,6 @@
       return  if showError err

       computeController.reset yes
-      reactor.dispatch actions.REMOVE_STACK, stack._id

 module.exports = {


Remove, not clear

Remove, not clear

--- client/apps/edit/components/admin/index.coffee
+++ client/apps/edit/components/admin/index.coffee
@@ -65,7 +65,7 @@
         { id: r._id, value: r.name }
       selected: (e, item, items) =>
         @article.save partner_ids: _.pluck items, 'id'
-      cleared: (e, item, items) =>
+      removed: (e, item, items) =>
         @article.save partner_ids: _.without(_.pluck(items, 'id'),item.id)
     if ids = @article.get('partner_ids')
       @partners = []


fixed reply box.

fixed reply box.

--- client/coffeescript/templates/reply_box.coffee
+++ client/coffeescript/templates/reply_box.coffee
@@ -17,24 +17,20 @@
           Session.set('current_post', @_id)
           Session.set('composing', '')
         event.stopPropagation()
-
-    #editing
-    """
-    keydown textarea[name='reply_text'],
-    keyup textarea[name='reply_text']
-    """: (event) ->
-      if not event.isImmediatePropagationStopped()
-        Session.set('composing', event.target.value)
-        Meteor.flush()
-        event.stopImmediatePropagation()

     #submit a reply.
     "click button[name='reply_submit']": (event) ->
       if not event.isImmediatePropagationStopped()
-        reply_content = Session.get('composing') #replyTextBox.value
+        tmpl = $(event.target).parent().parent().parent().parent()
+        reply_content = tmpl.find('#reply_text').val()
         if(reply_content=='')
           alert('Your reply is empty!')
         else
+          console.log {
+            content: reply_content,
+            parent_id: @_id,
+            domain: window.instance
+          }
           reply_id = Posts.insert(
             {
               content: reply_content,
@@ -42,7 +38,6 @@
               domain: window.instance
             }
           )
-          console.log('ID of new post: '+reply_id)
           Session.set('composing', undefined) #the clean up.
         event.stopImmediatePropagation()
         Meteor.flush()


kite: fix client side handlers

kite: fix client side handlers

--- client/landing/app/MainApp/kite/newkite.coffee
+++ client/landing/app/MainApp/kite/newkite.coffee
@@ -18,10 +18,10 @@
     @handlers =
       log   : (options)->
         log options.withArgs...
-        options.responseCallback()
+        options.responseCallback({withArgs: [{error: null, result: null}]})
       alert : (options)->
         alert options.withArgs...
-        options.responseCallback()
+        options.responseCallback({withArgs: [{error: null, result: null}]})

     @proto = new Bongo.dnodeProtocol.Session null, @handlers
     @proto.on 'request', (req)=>


KodingRouter: We need to call handleQuery before app opened.

--- client/landing/app/MainApp/kodingrouter.coffee
+++ client/landing/app/MainApp/kodingrouter.coffee
@@ -78,16 +78,15 @@
         app = 'Activity' if app is 'Home' and KD.isLoggedIn()

         @setPageTitle nicenames[app] ? app
-        appManager = KD.getSingleton "appManager"
-
-        if appManager.get app
-          appManager.tell app, "handleQuery", query
-        else
-          appManager.once "AppCreated", (appInstance) ->
-            appManager.tell app, "handleQuery", query
+        appManager  = KD.getSingleton "appManager"
+        handleQuery = appManager.tell.bind appManager, app, "handleQuery", query
+
+        appManager.once "AppCreated", handleQuery  unless appManager.get app

         appManager.open app, (appInstance)=>
           appInstance.setOption "initialRoute", @getCurrentPath()
+
+        handleQuery.call this  if appManager.get app

   handleNotFound:(route)->