Use denanning on both _hit_test and _index_data

Broken displaying the second discontinuous patches.

--- bokehjs/src/coffee/renderer/glyph/patches.coffee
+++ bokehjs/src/coffee/renderer/glyph/patches.coffee
@@ -5,36 +5,55 @@

 class PatchesView extends Glyph.View

+  _build_discontinuous_object: (nanned_qs) ->
+    # _s is @xs, @ys, @sxs, @sys
+    # an object of n 1-d arrays in either data or screen units
+    #
+    # Each 1-d array gets broken to an array of arrays split
+    # on any NaNs
+    #
+    # So:
+    # { 0: [x11, x12],
+    #   1: [x21, x22, x23],
+    #   2: [x31, NaN, x32]
+    # }
+    # becomes
+    # { 0: [[x11, x12]],
+    #   1: [[x21, x22, x23]],
+    #   2: [[x31],[x32]]
+    # }
+    ds = {}
+    for i in [0...nanned_qs.length]
+      ds[i] = []
+      qs = nanned_qs[i]
+      while qs.length > 0
+
+        nan_index = _.findLastIndex(qs, (q) ->  _.isNaN(q))
+
+        if nan_index >= 0
+          qs_part = qs.splice(nan_index)
+        else
+          qs_part = qs
+          qs = []
+
+        denanned = (q for q in qs_part when not _.isNaN(q))
+        ds[i].push(denanned)
+    return ds
+
+
   _index_data: () ->
     index = rbush()
     pts = []
+    xss = @_build_discontinuous_object(@xs)
+    yss = @_build_discontinuous_object(@ys)
+
     for i in [0...@xs.length]
-
-      xs = @xs[i]
-      ys = @ys[i]
-
-      while xs.length > 0
-
-        xs_nan_index = _.findLastIndex(xs, (x) ->  _.isNaN(x))
-        ys_nan_index = _.findLastIndex(ys, (y) ->  _.isNaN(y))
-
-        if xs_nan_index >= 0
-          xs_loop = xs.splice(xs_nan_index)
-        else
-          xs_loop = xs
-          xs = []
-
-        if ys_nan_index >= 0
-          ys_loop = ys.splice(ys_nan_index)
-        else
-          ys_loop = ys
-          ys = []
-
-        xs_push = (x for x in xs_loop when not _.isNaN(x))
-        ys_push = (y for y in ys_loop when not _.isNaN(y))
+      for j in [0...xss[i].length]
+        xs = xss[i][j]
+        ys = yss[i][j]
         pts.push([
-          _.min(xs_push), _.min(ys_push),
-          _.max(xs_push), _.max(ys_push),
+          _.min(xs), _.min(ys),
+          _.max(xs), _.max(ys),
           {'i': i}
         ])
     index.load(pts)
@@ -101,11 +120,17 @@

     candidates = (x[4].i for x in @index.search([x, y, x, y]))

+    sxss = @_build_discontinuous_object(@sxs)
+    syss = @_build_discontinuous_object(@sys)
+
     hits = []
     for i in [0...candidates.length]
       idx = candidates[i]
-      if hittest.point_in_poly(sx, sy, @sxs[idx], @sys[idx])
-        hits.push(idx)
+      sxs = sxss[idx]
+      sys = syss[idx]
+      for j in [0...sxs.length]
+        if hittest.point_in_poly(sx, sy, sxs[j], sys[j])
+          hits.push(idx)

     result = hittest.create_hit_test_result()
     result['1d'].indices = hits


これで、ほんとに。

これで、ほんとに。

--- scripts/cron.coffee
+++ scripts/cron.coffee
@@ -39,16 +39,16 @@
             robot.logger.debug 'cron07'
             getNextEvent( (result) ->
                 now = moment().format(YMD)
-                nextDate = moment(result)
-                next = nextDate.format(YMD)
+                next = moment(result).format(YMD)

                 robot.logger.debug 'cron07: now=' + now + ' ? next=' + next
                 if now is next
                     # 今日がBandroid開催日ならメッセージを出力
-                    md = nextDate.format('M月D日(ddd)')
-                    hm = nextDate.format('HH:mm')
+                    md = moment(result).format('M月D日(ddd)')
+                    hm = moment(result).format('HH:mm')
                     message = '今日 ' + md + ' は Bandroid の開催日です！\n開始予定時刻は ' + hm + ' です。'
                     robot.send {room: 'test'}, message
+                    robot.logger.debug 'send message: ' + message
             )
     )

@@ -60,17 +60,17 @@
             robot.logger.debug 'cron18'
             getNextEvent( (result) ->
                 now = moment().format(YMD)
-                nextDate = moment(result)
-                beforeNext = nextDate.add(-1, 'days').format(YMD)
-                next = nextDate.format(YMD)
+                beforeNext = moment(result).add(-1, 'days').format(YMD)
+                next = moment(result).format(YMD)

                 robot.logger.debug 'cron18: now=' + now + ' ? beforeNext=' + beforeNext
                 if now is beforeNext
                     # 明日がBandroid開催日ならメッセージを出力
-                    md = nextDate.format('M月D日(ddd)')
-                    hm = nextDate.format('HH:mm')
+                    md = moment(result).format('M月D日(ddd)')
+                    hm = moment(result).format('HH:mm')
                     message = '明日 ' + md + ' は Bandroid の開催日です！\n開始予定時刻は ' + hm + ' です。'
-                    robot.send {room: 'test'}, message
+                    # robot.send {room: 'test'}, message
+                    robot.logger.debug 'send message: ' + message
             )
     )


Update docs.coffee

Update docs.coffee

adjusted how the response is built

--- scripts/docs.coffee
+++ scripts/docs.coffee
@@ -50,9 +50,9 @@
         version = ''

     fetchResult getQueryUrl(version, query), (url) ->
-      response = "#{url}"
+      response = url
       if user
-        response = "#{user}: " + response
+        response = user + ": " + response

       if version == 'php' and /function/.test url
           robot.http(url).get() (err, res, body) ->


Fix overlay on navigation from beatmap discussion page

--- resources/assets/coffee/react/beatmap-discussions/beatmap-list.coffee
+++ resources/assets/coffee/react/beatmap-discussions/beatmap-list.coffee
@@ -31,6 +31,11 @@

   componentDidMount: =>
     $(document).on 'click.beatmapList', @hideSelector
+    @syncBlackout()
+
+
+  componentDidUpdate: =>
+    @syncBlackout()

   componentWillUnmount: =>
@@ -82,8 +87,6 @@
   setSelector: (state) =>
     return if @state.showingSelector == state

-    Blackout.toggle(state, 0.5)
-
     @setState showingSelector: state

@@ -94,6 +97,10 @@
     $.publish 'beatmapsetDiscussions:update', beatmapId: parseInt(e.currentTarget.dataset.id, 10)

+  syncBlackout: =>
+    Blackout.toggle(@state.showingSelector, 0.5)
+
+
   toggleSelector: (e) =>
     return if e.button != 0
     e.preventDefault()


Refactor jerk script

Refactor jerk script

--- scripts/jerk.coffee
+++ scripts/jerk.coffee
@@ -1,12 +1,12 @@
 module.exports = (robot) ->
   robot.hear /!jerk/i, (msg) ->
     msg
-      .http("https://www.reddit.com/r/circlejerk/.json")
+      .http("https://www.reddit.com/r/circlejerk.json")
       .query
         count: 25
         domain: "self.circlejerk"
       .get() (err, res, body) ->
-        resp = ""
+        resp = []
         results = JSON.parse(body)
         posts = results.data.children
         if results.error
@@ -14,5 +14,5 @@
             resp += err.message
         else
           post = msg.random posts
-          resp = "#{post.data.title}\n#{post.data.selftext}"
-        msg.send resp+          resp = [post.data.title, post.data.selftext]
+        msg.send resp...


Adds children()

Adds children()

--- src/pathname.coffee
+++ src/pathname.coffee
@@ -329,9 +329,10 @@
     elements.unshift('/') if @toString()[0] is '/'
     elements

+  children: (args...) -> @readdir(args...)
+

   # TODO
-  # children
   # siblings
   # chdir
   # relativeFrom


this require is no longer needed (dependency was already removed)

--- core/app/backbone/controllers/conversations_controller.coffee
+++ core/app/backbone/controllers/conversations_controller.coffee
@@ -1,4 +1,3 @@
-#= require './channels_controller'
 app = FactlinkApp

 class window.ConversationsController extends Backbone.Factlink.BaseController


Add interlink menu item

Add interlink menu item

--- menus/notational-velocity.cson
+++ menus/notational-velocity.cson
@@ -9,6 +9,10 @@
           'label': 'Toggle'
           'command': 'nvatom:toggle'
         }
+        {
+          'label': 'Open Interlink'
+          'command': 'nvatom:openInterlink'
+        }
       ]
     ]
   }


config cache timeout

config cache timeout

--- lib/middleware/api_cache.coffee
+++ lib/middleware/api_cache.coffee
@@ -5,7 +5,7 @@

 _ = require 'underscore'
 express = require 'express'
-{ CLIENT_CACHE_ROUTES, API_URL } = require '../../config'
+{ CLIENT_CACHE_ROUTES, CLIENT_CACHE_TIME, API_URL } = require '../../config'
 cache = require '../cache'
 request = require 'superagent'

@@ -27,7 +27,7 @@
       .set('X-XAPP-TOKEN': req.header 'X-XAPP-TOKEN')
       .end (r) ->
         return next r.error if r.error
-        cache.set key, r.text
+        cache.set key, r.text, CLIENT_CACHE_TIME
         res.send r.body

 app.use overrideAPIUrl


Fixed error: when allow change username was set to false, registration failed.

--- packages/rocketchat-lib/server/methods/setUsername.coffee
+++ packages/rocketchat-lib/server/methods/setUsername.coffee
@@ -3,12 +3,12 @@
 		if not Meteor.userId()
 			throw new Meteor.Error('invalid-user', "[methods] setUsername -> Invalid user")

-		unless RocketChat.settings.get("Accounts_AllowUsernameChange")
-			throw new Meteor.Error(403, "[methods] resetAvatar -> Invalid access")
+		user = Meteor.user()
+
+		if user.username? and not RocketChat.settings.get("Accounts_AllowUsernameChange")
+			throw new Meteor.Error(403, "[methods] setUsername -> Username change not allowed")

 		console.log '[methods] setUsername -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
-
-		user = Meteor.user()

 		if user.username is username
 			return username


Add rolling to section

Add rolling to section

--- server/index.coffee
+++ server/index.coffee
@@ -9,6 +9,7 @@
   secret: conf.cookie.secretKey
   cookie:
     maxAge: conf.cookie.maxAge
+  rolling: true
 app.use bodyParser.json()

 app.use require './api/login'


Save the questions if we've already accessed data.

* If #list is called before #questions, we store the questions at this
  moment to avoid unnecessary file access.

--- src/reporter.coffee
+++ src/reporter.coffee
@@ -36,15 +36,16 @@
   #  a callback is provided.
   @list = (options, cb) ->
     [cb, options] = [options, null] if typeof options is 'function'
+    reports = []

-    reports = []
-    directory = @options.directory
+    fs.readdirSync(@options.directory).forEach (file) ->
+      if file.match /.json$/
+        data = JSON.parse(fs.readFileSync path.join(@options.directory, file))

-    fs.readdirSync(directory).forEach (file) ->
-      if file.match /.json$/
-        data = fs.readFileSync path.join(directory, file)
-        snapshots = JSON.parse(data).snapshots
+        @_questions = data.questions unless @_questions?
+        snapshots = data.snapshots
         snapshots.forEach (report) -> reports.push report
+    , @

     reports.forEach (r) -> r.date = helper.format_date r.date


better debug on failed to resolve if misspelled extra extension

--- src/resolver.coffee
+++ src/resolver.coffee
@@ -40,8 +40,8 @@
     return false

 # resolver constructor
-Resolver = (@domains, @arbiters, @mainDomain, exts) ->
-  @finder = makeFinder(exts)
+Resolver = (@domains, @arbiters, @mainDomain, @exts) ->
+  @finder = makeFinder(@exts)
   return

 # locate location of file from absReq (assumed only called on files that pass isLegalRequire)
@@ -74,7 +74,7 @@
     return [found, dom, false] if found = @finder(@domains[dom], absReq + '/index')

-  throw new Error("modul8::analysis could not resolve a require for #{reqStr} from #{domain} - looked in #{scannable}")
+  throw new Error("modul8::analysis could not resolve a require for #{reqStr} from #{domain} - looked in #{scannable}, trying extensions #{@exts[1...]}")

 module.exports = {
   isLegalRequire


Get absolute path of root.

Get absolute path of root.

--- src/resolver.coffee
+++ src/resolver.coffee
@@ -4,8 +4,12 @@
 {join}    = require 'path'
 {sep}     = require './utils'
 {uniq}    = require './utils'
+{resolve} = require 'path'

 module.exports = (root) ->
+  # Get absolute path
+  root = resolve root
+
   # Maintain a cache of resolved paths.
   cache = {}

@@ -30,6 +34,8 @@
     if process.env.NODE_PATH
       paths = paths.concat process.env.NODE_PATH.split ':'
     paths
+
+  console.log modulePaths

   # Resolve directory/npm module to index/main file.
   resolveDirectory = (path, cb) ->


Delete trailing whitespace.

Delete trailing whitespace.

--- src/rewriter.coffee
+++ src/rewriter.coffee
@@ -70,14 +70,14 @@
   # its paired close. We have the mis-nested outdent case included here for
   # calls that close on the same line, just before their outdent.
   closeOpenCalls: ->
-
+
     condition = (token, i) ->
       token[0] in [')', 'CALL_END'] or
       token[0] is 'OUTDENT' and @tag(i - 1) is ')'
-
+
     action = (token, i) ->
       @tokens[if token[0] is 'OUTDENT' then i - 1 else i][0] = 'CALL_END'
-
+
     @scanTokens (token, i) ->
       @detectEnd i + 1, condition, action if token[0] is 'CALL_START'
       1
@@ -85,13 +85,13 @@
   # The lexer has tagged the opening parenthesis of an indexing operation call.
   # Match it with its paired close.
   closeOpenIndexes: ->
-
-    condition = (token, i) ->
+
+    condition = (token, i) ->
       token[0] in [']', 'INDEX_END']
-
-    action = (token, i) ->
+
+    action = (token, i) ->
       token[0] = 'INDEX_END'
-
+
     @scanTokens (token, i) ->
       @detectEnd i + 1, condition, action if token[0] is 'INDEX_START'
       1
@@ -99,29 +99,29 @@
   # Object literals may be written with implicit braces, for simple cases.
   # Insert the missing braces here, so that the parser doesn't have to.
   addImplicitBraces: ->
-
+
     stack       = []
     start       = null
     startsLine  = null
     sameLine    = yes
     startIndent = 0
-
+
     condition = (token, i) ->
       [one, two, three] = @tokens[i + 1 .. i + 3]
       return no if 'HERECOMMENT' is one?[0]
       [tag] = token
       sameLine = no if tag in LINEBREAKS
       ((tag in ['TERMINATOR', 'OUTDENT'] or (tag in IMPLICIT_END and sameLine)) and
-          ((!startsLine and @tag(i - 1) isnt ',') or
+          ((!startsLine and @tag(i - 1) isnt ',') or
           not (two?[0] is ':' or one?[0] is '@' and three?[0] is ':'))) or
         (tag is ',' and one and
           one[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT'])
-
+
     action = (token, i) ->
       tok = ['}', '}', token[2]]
       tok.generated = yes
       @tokens.splice i, 0, tok
-
+
     @scanTokens (token, i, tokens) ->
       if (tag = token[0]) in EXPRESSION_START
         stack.push [(if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag), i]
@@ -149,9 +149,9 @@
   # Insert the implicit parentheses here, so that the parser doesn't have to
   # deal with them.
   addImplicitParentheses: ->
-
+
     noCall = seenSingle = seenControl = no
-
+
     condition = (token, i) ->
       [tag] = token
       return yes if not seenSingle and token.fromThen
@@ -163,10 +163,10 @@
         (tag isnt 'INDENT' or
           (@tag(i - 2) not in ['CLASS', 'EXTENDS'] and @tag(i - 1) not in IMPLICIT_BLOCK and
           not ((post = @tokens[i + 1]) and post.generated and post[0] is '{')))
-
-    action = (token, i) ->
+
+    action = (token, i) ->
       @tokens.splice i, 0, ['CALL_END', ')', token[2]]
-
+
     @scanTokens (token, i, tokens) ->
       tag     = token[0]
       noCall  = yes if tag in ['CLASS', 'IF']
@@ -192,16 +192,16 @@
   # blocks, so it doesn't need to. ')' can close a single-line block,
   # but we need to make sure it's balanced.
   addImplicitIndentation: ->
-
+
     starter = indent = outdent = null
-
+
     condition = (token, i) ->
       token[1] isnt ';' and token[0] in SINGLE_CLOSERS and
       not (token[0] is 'ELSE' and starter not in ['IF', 'THEN'])
-
+
     action = (token, i) ->
       @tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent
-
+
     @scanTokens (token, i, tokens) ->
       [tag] = token
       if tag is 'TERMINATOR' and @tag(i + 1) is 'THEN'
@@ -228,15 +228,15 @@
   # Tag postfix conditionals as such, so that we can parse them with a
   # different precedence.
   tagPostfixConditionals: ->
-
+
     original = null
-
-    condition = (token, i) ->
+
+    condition = (token, i) ->
       token[0] in ['TERMINATOR', 'INDENT']
-
+
     action = (token, i) ->
       original[0] = 'POST_' + original[0] if token[0] isnt 'INDENT'
-
+
     @scanTokens (token, i) ->
       return 1 unless token[0] is 'IF'
       original = token


Lowercased the Memecode, escaped captions

Lowercased the Memecode, allowing for mixed case entry. Because iPhone always wants to capitalize Morpheus.

Also escaped captions in URL entry. Makes URLS less human readable at times, but allows for functioning punctuation.

--- src/memes.coffee
+++ src/memes.coffee
@@ -63,9 +63,9 @@

   robot.respond /meme me (\w+) (\"[^"]+\") (\"[^"]+\")/i, (msg) ->

-    meme = if checkCode(msg.match[1], memes) then msg.match[1] else 'doge'
+    meme = if checkCode(msg.match[1].toLowerCase(), memes) then msg.match[1].toLowerCase() else 'doge'
     top    = msg.match[2].replace(/"/g, '').trim().replace(/\s+/g, '-')
     bottom = msg.match[3].replace(/"/g, '').trim().replace(/\s+/g, '-')

-    msg.send "http://memegen.link/#{meme}/#{top}/#{bottom}.jpg"
+    msg.send "http://memegen.link/#{meme}/#{escape(top)}/#{escape(bottom)}.jpg"


Ensure that model actions also handle the new response keys correctly

--- src/model.coffee
+++ src/model.coffee
@@ -3,6 +3,7 @@
 Backbone = require 'backbone'
 Backbone.$ = require 'jquery' # TODO remove after upgrading to backbone 1.2+
 inflection = require 'inflection'
+{ knownResponseKeys } = require './constants.coffee'

 Utils = require './utils'
 StorageManager = require './storage-manager'
@@ -198,7 +199,7 @@
     results = resp['results']
     return if _.isEmpty(results)

-    keys = _.reject(_.keys(resp), (key) -> key == 'count' || key == 'results')
+    keys = _.without(_.keys(resp), knownResponseKeys...)
     primaryModelKey = results[0]['key']
     keys.splice(keys.indexOf(primaryModelKey), 1)
     keys.push(primaryModelKey)


Return Internal Data as Resolve Values

Return Internal Data as Resolve Values

Fixes some broken places in the chain of data references. This would've
lead to some errors where data was not correctly updated in views.

--- src/model.coffee
+++ src/model.coffee
@@ -277,7 +277,7 @@
           _data.all.splice(0, data.length)
           [].push.apply(_data.all, data)
           store.setItem("#{name}.all", _data.all)
-          return _data
+          return _data.all

         ###
         # @method Update Single Entry from Collection
@@ -337,7 +337,7 @@
           response.data = config.transformResponse(response.data, 'array')

           # replace array items with new data
-          Data.replace(response.data)
+          response.data = Data.replace(response.data)

           return $q.when(response)

@@ -355,9 +355,7 @@
             throw new Error "#{name} Model: Expected object, got #{typeof response.data}"

           response.data = config.transformResponse(response.data, 'one')
-
-          Data.replace(response.data)
-
+          response.data = Data.replace(response.data)
           return $q.when(response)

       ###
@@ -384,8 +382,7 @@
             throw new Error "Expected object, got #{typeof res.data}"

           res.data = config.transformResponse(res.data, 'one')
-
-          Data.updateEntry res.data, config.matchingCriteria(res.data)
+          res.data = Data.updateEntry res.data, config.matchingCriteria(res.data)
           return $q.when(res)

       ###


fix #65

fix #65

--- src/model.coffee
+++ src/model.coffee
@@ -336,7 +336,12 @@
     #
     # Returns {Object} target
     @cast: (attributes, target = {}) ->
-        castObject attributes, @schema, target, @name
+        if @name isnt 'ClassFromGetModel'
+            displayName = @name
+        else
+            displayName = @displayName
+
+        castObject attributes, @schema, target, displayName

     @destroyAll: (params, callback) ->


Added steps indexes to slider map

Added steps indexes to slider map

--- lib/foundry-xray/app/assets/javascripts/application.js.coffee
+++ lib/foundry-xray/app/assets/javascripts/application.js.coffee
@@ -69,8 +69,9 @@
     @input.transforms.each (entry) =>
       height = entry.length/(@input.events.length-1)*100
       top    = 100-entry.id/(@input.events.length-1)*100-height
+      label  = "#{entry.label} (#{entry.id}+#{entry.length})"

-      @transforms.append $("
#{entry.label}
")
+      @transforms.append $("
#{label}
")
         .attr("style", "top: #{top}%; height: #{height}%;")
         .click (e) =>
           e.stopPropagation()


Loads for those that haven't been commented.

--- public/dreamcatcher/controllers/comment_controller.coffee
+++ public/dreamcatcher/controllers/comment_controller.coffee
@@ -48,22 +48,17 @@

   loadComments: (entryId) ->
     #show loading wheel
-    Dreamcatcher.Models.Comment.findEntryComments entryId,{},@callback('populateComments')
+    Dreamcatcher.Models.Comment.findEntryComments entryId,{},@callback('populateComments',entryId)

-  populateComments: (comments) ->
-    entryId = comments[0].entry_id if comments.length > 0
+  populateComments: (entryId,comments) ->
     entry = @getEntry entryId
     newCount = @getNewCommentCount entry
     totalCount = comments.length
-    @displayComments entry,newCount,totalCount,comments
-
-  displayComments: (entry, newCount, totalCount, comments) ->
     commentsPanel = $(".commentsTarget",entry)
     commentsPanel.html @view('list',{userId: @currentUserId, newCount: newCount, totalCount: totalCount, comments: comments})

     #remove all delete buttons which should  not be accessed
     entryUserId = entry.data("userid")
-
     if @currentUserId isnt entryUserId or not $("#entryField").data 'owner'
       $(".deleteComment",commentsPanel).each (index,element) =>
         commentUserId = parseInt $(element).data('userid')
@@ -73,17 +68,15 @@

     #TODO: hide loading wheel

-    if @entryView
+    if @entryView #show all for entryView
       $(".prevCommentWrap",entry).show()
       #if not @entryView or (totalCount > 0 and newCount < totalCount) #show only new comments initially
-    else
+    else #only show new ones, or at least 2
       $(entry).addClass("expanded")
-      indexToStartShowing = totalCount - Math.max(newCount,2) #show all new, or at least 2 --- TODO: This may change
+      indexToStartShowing = totalCount - Math.max(newCount,2)
       $(".showAll",commentsPanel).show() if indexToStartShowing > 0 #only show showAll button if some left to show
       $(".prevCommentWrap",entry).each (index,element) ->
         $(element).show() if index >= indexToStartShowing
-    #else #just show all of them!
-

   created: (data) ->
     comment = data.comment
@@ -108,10 +101,10 @@
     else if $(".prevCommentWrap",entry).length > 0 #collapsed, been expanded, comments already loaded, just expand
       $(".commentsTarget",entry).show()
       entry.addClass("expanded")
-    else if @getTotalCommentCount(entry) > 0
+    else #if @getTotalCommentCount(entry) > 0
       @loadComments entryId
-    else
-      @displayComments entry,0,0,{}
+    #else
+    #  @displayComments entry,0,0,{}

   '.showAll click': (el) ->
     entry = @getEntryFromElement el


activity: use 'showErr' for error handling

--- client/Social/Activity/views/settingsview.coffee
+++ client/Social/Activity/views/settingsview.coffee
@@ -100,7 +100,7 @@
     KD.singletons.appManager.tell 'Activity', 'delete', {id}, (err) =>

       if err
-        KD.showErrorNotification err, { userMessage : "You are not allowed to delete this post." }
+        KD.showError err
         @emit 'ActivityDeleteFailed'
       else
         @emit 'ActivityDeleteSucceeded'


Added pistachio changes for non-dynamic elements

--- client/app/lib/providers/snapshotlistitem.coffee
+++ client/app/lib/providers/snapshotlistitem.coffee
@@ -4,6 +4,7 @@
 remote              = require('app/remote').getInstance()
 {JSnapshot}         = remote.api

+JView               = require '../jview'
 nicetime            = require '../util/nicetime'

@@ -18,8 +19,6 @@

     @initViews()
     @setLabel data.label
-    @setCreatedAt data.createdAt
-    @setStorageSize data.storageSize

   ###*
@@ -28,7 +27,16 @@
   @notify: (msg = "") ->

     new kd.NotificationView content: msg
-    return
+
+
+  ###*
+   * Return a nicely formatted created at.
+  ###
+  @prettyCreatedAt: (createdAt) ->
+
+    createdAt = new Date(createdAt) if typeof createdAt is 'string'
+    createdAtAgo = nicetime (createdAt - Date.now()) / 1000
+    return createdAtAgo

   ###*
@@ -37,61 +45,68 @@
   initViews: ->

     data = @getData()
-    @editView = new kd.View
-      cssClass: 'edit hidden'
-
-    @editView.addSubView @editView.edit = new kd.HitEnterInputView
+    @editInput = new kd.HitEnterInputView
       type        : 'text'
       placeholder : 'Snapshot Name'
       cssClass    : 'label'
       callback    : @bound 'renameSnapshot'

-    @editView.addSubView wrapper = new kd.CustomHTMLView
-      cssClass: 'buttons'
-
-    wrapper.addSubView @editView.renameBtn = new kd.ButtonView
+    @editRenameBtn = new kd.ButtonView
       title    : 'rename'
       cssClass : 'solid green compact rename'
       callback : @bound 'renameSnapshot'

-    wrapper.addSubView @editView.cancelBtn = new kd.View
+    @editCancelBtn = new kd.View
       partial  : 'cancel'
       tagName  : 'span'
       tagName  : 'span'
       cssClass : 'cancel'
       click    : @bound 'toggleEditable'

-    @infoView = new kd.View
-      cssClass: 'info'
-
-    @infoView.addSubView @infoView.labelView = new kd.View
+    @labelView = new kd.View
       tagName  : 'span'
       cssClass : 'label'
       click    : @bound 'toggleEditable'

-    @infoView.addSubView @infoView.storageSizeView = new kd.View
-      tagName  : 'span'
-      cssClass : 'storage-size'
-
-    @infoView.addSubView @infoView.createdAtView = new kd.View
-      tagName  : 'span'
-      cssClass : 'created-at'
-
-    @infoView.addSubView wrapper = new kd.CustomHTMLView
-      cssClass: 'buttons'
-
-    wrapper.addSubView @infoView.renameSnapshotBtn = new kd.ButtonView
+    @infoRenameBtn = new kd.ButtonView
       iconOnly : true
       cssClass : 'rename'
       callback : @bound 'toggleEditable'

-    wrapper.addSubView @infoView.deleteSnapshotBtn = new kd.ButtonView
+    @infoDeleteBtn = new kd.ButtonView
       iconOnly : true
       cssClass : 'delete'
       callback : @bound "confirmDeleteSnapshot"

-    @addSubView @editView
-    @addSubView @infoView
+    @addSubView @editView = new JView
+      cssClass: 'edit hidden'
+      pistachioParams: {@editInput, @editRenameBtn, @editCancelBtn}
+      pistachio: """
+

+          {{> editInput}}
+

+            {{> editRenameBtn}}
+            {{> editCancelBtn}}
+

+

+        """
+
+    @addSubView @infoView = new JView
+      cssClass: 'info'
+      pistachioParams: {@labelView, @infoRenameBtn, @infoDeleteBtn}
+      pistachio: """
+

+          {{> labelView}}
+          (#{data.storageSize}GB)
+
+            #{SnapshotListItem.prettyCreatedAt data.createdAt}
+
+

+            {{> infoRenameBtn}}
+            {{> infoDeleteBtn}}
+

+

+        """

   ###*
@@ -127,7 +142,6 @@
         @getDelegate().emit 'DeleteSnapshot', this
         @destroy()
       .catch (err) -> kd.warn err
-    return

   partial: ->
@@ -139,7 +153,7 @@
   ###
   renameSnapshot: ->

-    label        = @editView.edit.getValue()
+    label        = @editInput.getValue()
     data         = @getData()
     {snapshotId} = data

@@ -167,20 +181,6 @@
           return

         rename snapshot
-    return
-
-
-  ###*
-   * Set the value of the createdAt UI element
-   *
-   * @param {Date|String} createdAt - The value to display createdAt
-  ###
-  setCreatedAt: (createdAt) ->
-
-    createdAt = new Date(createdAt) if typeof createdAt is 'string'
-    createdAtAgo = nicetime (createdAt - Date.now()) / 1000
-    @infoView.createdAtView.updatePartial createdAtAgo
-    return

   ###*
@@ -190,20 +190,8 @@
   ###
   setLabel: (label) ->

-    @infoView.labelView.updatePartial label
-    @editView.edit.setValue label
-    return
-
-
-  ###*
-   * Set the value of the Storage Size UI element
-   *
-   * @param {Number} storageSize
-  ###
-  setStorageSize: (storageSize) ->
-
-    @infoView.storageSizeView.updatePartial "(#{storageSize}GB)"
-    return
+    @labelView.updatePartial label
+    @editInput.setValue label

   ###*
@@ -214,7 +202,7 @@
     if @infoView.$().is ":visible"
       @infoView.hide()
       @editView.show()
-      kd.utils.defer @editView.edit.bound "setFocus"
+      kd.utils.defer @editInput.bound "setFocus"
     else
       @infoView.show()
       @editView.hide()


fix missed class rename reference

fix missed class rename reference

--- resources/assets/coffee/react/beatmapset-page/hype.coffee
+++ resources/assets/coffee/react/beatmapset-page/hype.coffee
@@ -51,7 +51,7 @@

         div className: "#{bn}__lights",
           for i in _.times(@props.beatmapset.hype.required)
-            state = if i < @props.beatmapset.hype.current then 'on' else 'off-light'
+            state = if i < @props.beatmapset.hype.current then 'on' else 'off'
             div
               key: i
               className: "bar bar--beatmapset-hype bar--beatmapset-#{state}"


Fix for settings view

Fix for settings view

--- lib/highlighted-area-view.coffee
+++ lib/highlighted-area-view.coffee
@@ -26,7 +26,7 @@
     @removeMarkers()

     editor = @getActiveEditor()
-
+    return unless editor
     return if editor.getSelection().isEmpty()
     return unless @isWordSelected(editor.getSelection())


remove providers namespace commands

remove providers namespace commands

--- src/steroids.coffee
+++ src/steroids.coffee
@@ -106,30 +106,6 @@
         process.exit 1

     switch firstOption
-
-      when "providers"
-        providers = new Providers
-        providers.listProviders()
-
-      when "providers:my"
-        providers = new Providers
-        providers.listMyProviders()
-
-      when "providers:add"
-        if otherOptions.length==0
-          console.log 'provider should be specified'
-          process.exit 1
-
-        providers = new Providers
-        providers.addProvider(otherOptions[0])
-
-      when "providers:remove"
-        if otherOptions.length==0
-          console.log 'provider should be specified'
-          process.exit 1
-
-        providers = new Providers
-        providers.removeProvider(otherOptions[0])

       when "resources:init"
         unless argv.provider


issue #25 tests passing fix

issue #25 tests passing fix

--- src/scripts/ui-scroll.coffee
+++ src/scripts/ui-scroll.coffee
@@ -307,7 +307,7 @@
 									#log "appending... requested #{bufferSize} records starting from #{next}"
 									datasource.get next, bufferSize,
 									(result) ->
-										return if rid isnt ridActual
+										return if rid and rid isnt ridActual
 										newItems = []
 										if result.length == 0
 											eof = true
@@ -327,7 +327,7 @@
 									#log "prepending... requested #{size} records starting from #{start}"
 									datasource.get first-bufferSize, bufferSize,
 									(result) ->
-										return if rid isnt ridActual
+										return if rid and rid isnt ridActual
 										newItems = []
 										if result.length == 0
 											bof = true


doAdjustment merged into AdjustBuffer

doAdjustment merged into AdjustBuffer

--- src/scripts/ui-scroll.coffee
+++ src/scripts/ui-scroll.coffee
@@ -144,257 +144,6 @@
 							adapter.isLoading = value
 							setValueChain($scope, $attr.isLoading, value) if $attr.isLoading
 							datasource.loading(value) if typeof datasource.loading is 'function'
-
-						ridActual = 0
-						first = 1
-						next = 1
-						buffer = []
-						pending = []
-						eof = false
-						bof = false
-
-						#removes items from start (including) through stop (excluding)
-						removeFromBuffer = (start, stop)->
-							for i in [start...stop]
-								buffer[i].scope.$destroy()
-								buffer[i].element.remove()
-							buffer.splice start, stop - start
-
-						reload = ->
-							ridActual++
-							first = 1
-							next = 1
-							removeFromBuffer(0, buffer.length)
-							builder.topPadding(0)
-							builder.bottomPadding(0)
-							pending = []
-							eof = false
-							bof = false
-							adjustBuffer(ridActual)
-
-						bottomVisiblePos = ->
-							viewport.scrollTop() + viewport.outerHeight()
-
-						topVisiblePos = ->
-							viewport.scrollTop()
-
-						shouldLoadBottom = ->
-							!eof && builder.bottomDataPos() < bottomVisiblePos() + bufferPadding()
-
-						clipBottom = ->
-							# clip the invisible items off the bottom
-							bottomHeight = 0 #builder.bottomPadding()
-							overage = 0
-
-							for i in [buffer.length-1..0]
-								item = buffer[i]
-								itemTop = item.element.offset().top
-								newRow = rowTop isnt itemTop
-								rowTop = itemTop
-								itemHeight = item.element.outerHeight(true) if newRow
-								if (builder.bottomDataPos() - bottomHeight - itemHeight > bottomVisiblePos() + bufferPadding())
-									bottomHeight += itemHeight if newRow
-									overage++
-									eof = false
-								else
-									break if newRow
-									overage++
-
-							if overage > 0
-								builder.bottomPadding(builder.bottomPadding() + bottomHeight)
-								removeFromBuffer(buffer.length - overage, buffer.length)
-								next -= overage
-								#log "clipped off bottom #{overage} bottom padding #{builder.bottomPadding()}"
-
-						shouldLoadTop = ->
-							!bof && (builder.topDataPos() > topVisiblePos() - bufferPadding())
-
-						clipTop = ->
-							# clip the invisible items off the top
-							topHeight = 0
-							overage = 0
-							for item in buffer
-								itemTop = item.element.offset().top
-								newRow = rowTop isnt itemTop
-								rowTop = itemTop
-								itemHeight = item.element.outerHeight(true) if newRow
-								if (builder.topDataPos() + topHeight + itemHeight < topVisiblePos() - bufferPadding())
-									topHeight += itemHeight if newRow
-									overage++
-									bof = false
-								else
-									break if newRow
-									overage++
-							if overage > 0
-								builder.topPadding(builder.topPadding() + topHeight)
-								removeFromBuffer(0, overage)
-								first += overage
-								#log "clipped off top #{overage} top padding #{builder.topPadding()}"
-
-						enqueueFetch = (rid, direction)->
-							if (!adapter.isLoading)
-								loading(true)
-							if pending.push(direction) == 1
-								fetch(rid)
-
-						insert = (index, item) ->
-							itemScope = $scope.$new()
-							itemScope[itemName] = item
-							toBeAppended = index > first
-							itemScope.$index = index
-							itemScope.$index-- if toBeAppended
-							wrapper =
-								scope: itemScope
-
-							linker itemScope, (clone) ->
-								wrapper.element = clone
-								wrapper.toBeAppended = toBeAppended
-								if toBeAppended
-									if index == next
-										wrapper.doInsert = ->
-											builder.append clone
-											builder.bottomPadding(Math.max(0,builder.bottomPadding() - wrapper.element.outerHeight(true)))
-										buffer.push wrapper
-									else
-										wrapper.doInsert = ->
-											buffer[index-first-1].element.after clone
-										buffer.splice index-first+1, 0, wrapper
-								else
-									wrapper.doInsert = ->
-										builder.prepend clone
-										# an element is inserted at the top
-										newHeight = builder.topPadding() - wrapper.element.outerHeight(true)
-										# adjust padding to prevent it from visually pushing everything down
-										if newHeight >= 0
-											# if possible, reduce topPadding
-											builder.topPadding(newHeight)
-										else
-											# if not, increment scrollTop
-											viewport.scrollTop(viewport.scrollTop() + wrapper.element.outerHeight(true))
-									buffer.unshift wrapper
-
-						doAdjustment = (rid, finalize)->
-							#log "top {actual=#{builder.topDataPos()} visible from=#{topVisiblePos()} bottom {visible through=#{bottomVisiblePos()} actual=#{builder.bottomDataPos()}}"
-							if shouldLoadBottom()
-								enqueueFetch(rid, true)
-							else
-								enqueueFetch(rid, false) if shouldLoadTop()
-							finalize(rid) if finalize
-							if pending.length == 0
-								topHeight = 0
-								for item in buffer
-									itemTop = item.element.offset().top
-									newRow = rowTop isnt itemTop
-									rowTop = itemTop
-									itemHeight = item.element.outerHeight(true) if newRow
-									if newRow and (builder.topDataPos() + topHeight + itemHeight < topVisiblePos())
-										topHeight += itemHeight
-									else
-										topVisible(item) if newRow
-										break
-
-						adjustBuffer = (rid, newItems, finalize)->
-							if newItems
-								$timeout ->
-									prepended = []
-									for wrapper in buffer
-										if wrapper.element.parent().length == 0
-											if wrapper.toBeAppended
-												wrapper.doInsert()
-											else
-												prepended.unshift wrapper
-									# prepended items have to be inserted from the bottom up
-									for wrapper in prepended
-										wrapper.doInsert()
-									doAdjustment(rid, finalize)
-							else
-								doAdjustment(rid, finalize)
-
-						finalize = (rid, newItems)->
-							adjustBuffer rid, newItems, ->
-								pending.shift()
-								if pending.length == 0
-									loading(false)
-								else
-									fetch(rid)
-
-						fetch = (rid) ->
-							direction = pending[0]
-							#log "Running fetch... #{{true:'bottom', false: 'top'}[direction]} pending #{pending.length}"
-							if direction
-								if buffer.length && !shouldLoadBottom()
-									finalize(rid)
-								else
-									#log "appending... requested #{bufferSize} records starting from #{next}"
-									datasource.get next, bufferSize,
-									(result) ->
-										return if (rid and rid isnt ridActual) or $scope.$$destroyed
-										if result.length < bufferSize
-											eof = true
-											builder.bottomPadding(0)
-											#log "eof is reached"
-										if result.length > 0
-											clipTop()
-											for item in result
-												insert ++next, item
-											#log "appended: requested #{bufferSize} received #{result.length} buffer size #{buffer.length} first #{first} next #{next}"
-										finalize rid, result.length > 0
-							else
-								if buffer.length && !shouldLoadTop()
-									finalize(rid)
-								else
-									#log "prepending... requested #{size} records starting from #{start}"
-									datasource.get first-bufferSize, bufferSize,
-									(result) ->
-										return if (rid and rid isnt ridActual) or $scope.$$destroyed
-										if result.length < bufferSize
-											bof = true
-											builder.topPadding(0)
-											#log "bof is reached"
-										if result.length > 0
-											clipBottom() if buffer.length
-											for i in [result.length-1..0]
-												insert --first, result[i]
-											#log "prepended: requested #{bufferSize} received #{result.length} buffer size #{buffer.length} first #{first} next #{next}"
-										finalize rid, result.length > 0
-
-						# events and bindings
-
-						resizeAndScrollHandler = ->
-							if !$rootScope.$$phase && !adapter.isLoading
-								adjustBuffer()
-								$scope.$apply()
-
-						wheelHandler = (event) ->
-							scrollTop = viewport[0].scrollTop
-							yMax = viewport[0].scrollHeight - viewport[0].clientHeight
-							if (scrollTop is 0 and not bof) or (scrollTop is yMax and not eof)
-								event.preventDefault()
-
-						viewport.bind 'resize', resizeAndScrollHandler
-						viewport.bind 'scroll', resizeAndScrollHandler
-						viewport.bind 'mousewheel', wheelHandler
-
-						$scope.$watch datasource.revision, reload
-
-						if datasource.scope
-							eventListener = datasource.scope.$new()
-						else
-							eventListener = $scope.$new()
-
-						$scope.$on '$destroy', ->
-							for item in buffer
-								item.scope.$destroy()
-								item.element.remove()
-							viewport.unbind 'resize', resizeAndScrollHandler
-							viewport.unbind 'scroll', resizeAndScrollHandler
-							viewport.unbind 'mousewheel', wheelHandler
-
-
-						# adapter initializing
-
-						adapter = {}
-						adapter.isLoading = false

 						removeElement =
 							if $animate
@@ -413,6 +162,253 @@
 									deferred = $q.defer()
 									deferred.resolve()
 									deferred.promise
+
+						ridActual = 0
+						first = 1
+						next = 1
+						buffer = []
+						pending = []
+						eof = false
+						bof = false
+
+						#removes items from start (including) through stop (excluding)
+						removeFromBuffer = (start, stop)->
+							for i in [start...stop]
+								buffer[i].scope.$destroy()
+								buffer[i].element.remove()
+							buffer.splice start, stop - start
+
+						reload = ->
+							ridActual++
+							first = 1
+							next = 1
+							removeFromBuffer(0, buffer.length)
+							builder.topPadding(0)
+							builder.bottomPadding(0)
+							pending = []
+							eof = false
+							bof = false
+							adjustBuffer ridActual
+
+						bottomVisiblePos = ->
+							viewport.scrollTop() + viewport.outerHeight()
+
+						topVisiblePos = ->
+							viewport.scrollTop()
+
+						shouldLoadBottom = ->
+							!eof && builder.bottomDataPos() < bottomVisiblePos() + bufferPadding()
+
+						clipBottom = ->
+							# clip the invisible items off the bottom
+							bottomHeight = 0 #builder.bottomPadding()
+							overage = 0
+
+							for i in [buffer.length-1..0]
+								item = buffer[i]
+								itemTop = item.element.offset().top
+								newRow = rowTop isnt itemTop
+								rowTop = itemTop
+								itemHeight = item.element.outerHeight(true) if newRow
+								if (builder.bottomDataPos() - bottomHeight - itemHeight > bottomVisiblePos() + bufferPadding())
+									bottomHeight += itemHeight if newRow
+									overage++
+									eof = false
+								else
+									break if newRow
+									overage++
+
+							if overage > 0
+								builder.bottomPadding(builder.bottomPadding() + bottomHeight)
+								removeFromBuffer(buffer.length - overage, buffer.length)
+								next -= overage
+								#log "clipped off bottom #{overage} bottom padding #{builder.bottomPadding()}"
+
+						shouldLoadTop = ->
+							!bof && (builder.topDataPos() > topVisiblePos() - bufferPadding())
+
+						clipTop = ->
+							# clip the invisible items off the top
+							topHeight = 0
+							overage = 0
+							for item in buffer
+								itemTop = item.element.offset().top
+								newRow = rowTop isnt itemTop
+								rowTop = itemTop
+								itemHeight = item.element.outerHeight(true) if newRow
+								if (builder.topDataPos() + topHeight + itemHeight < topVisiblePos() - bufferPadding())
+									topHeight += itemHeight if newRow
+									overage++
+									bof = false
+								else
+									break if newRow
+									overage++
+							if overage > 0
+								builder.topPadding(builder.topPadding() + topHeight)
+								removeFromBuffer(0, overage)
+								first += overage
+								#log "clipped off top #{overage} top padding #{builder.topPadding()}"
+
+						enqueueFetch = (rid, direction)->
+							if (!adapter.isLoading)
+								loading(true)
+							if pending.push(direction) == 1
+								fetch(rid)
+
+						insert = (index, item) ->
+							itemScope = $scope.$new()
+							itemScope[itemName] = item
+							toBeAppended = index > first
+							itemScope.$index = index
+							itemScope.$index-- if toBeAppended
+							wrapper =
+								scope: itemScope
+
+							linker itemScope, (clone) ->
+								wrapper.element = clone
+								wrapper.toBeAppended = toBeAppended
+								if toBeAppended
+									if index == next
+										wrapper.doInsert = ->
+											builder.append clone
+											builder.bottomPadding(Math.max(0,builder.bottomPadding() - wrapper.element.outerHeight(true)))
+										buffer.push wrapper
+									else
+										wrapper.doInsert = ->
+											buffer[index-first-1].element.after clone
+										buffer.splice index-first+1, 0, wrapper
+								else
+									wrapper.doInsert = ->
+										builder.prepend clone
+										# an element is inserted at the top
+										newHeight = builder.topPadding() - wrapper.element.outerHeight(true)
+										# adjust padding to prevent it from visually pushing everything down
+										if newHeight >= 0
+											# if possible, reduce topPadding
+											builder.topPadding(newHeight)
+										else
+											# if not, increment scrollTop
+											viewport.scrollTop(viewport.scrollTop() + wrapper.element.outerHeight(true))
+									buffer.unshift wrapper
+
+						adjustBuffer = (rid, finalize)->
+							# We need the item bindings to be processed before we can do adjustment
+							$timeout ->
+								prepended = []
+								for wrapper in buffer
+									if wrapper.element.parent().length == 0
+										if wrapper.toBeAppended
+											wrapper.doInsert()
+										else
+											prepended.unshift wrapper
+								# prepended items have to be inserted from the bottom up
+								for wrapper in prepended
+									wrapper.doInsert()
+								# doAdjustment(rid, finalize)
+								#log "top {actual=#{builder.topDataPos()} visible from=#{topVisiblePos()} bottom {visible through=#{bottomVisiblePos()} actual=#{builder.bottomDataPos()}}"
+								if shouldLoadBottom()
+									enqueueFetch(rid, true)
+								else
+									enqueueFetch(rid, false) if shouldLoadTop()
+								finalize(rid) if finalize
+								if pending.length == 0
+									topHeight = 0
+									for item in buffer
+										itemTop = item.element.offset().top
+										newRow = rowTop isnt itemTop
+										rowTop = itemTop
+										itemHeight = item.element.outerHeight(true) if newRow
+										if newRow and (builder.topDataPos() + topHeight + itemHeight < topVisiblePos())
+											topHeight += itemHeight
+										else
+											topVisible(item) if newRow
+											break
+
+						finalize = (rid) ->
+							adjustBuffer rid, ->
+								pending.shift()
+								if pending.length == 0
+									loading(false)
+								else
+									fetch(rid)
+
+						fetch = (rid) ->
+							direction = pending[0]
+							#log "Running fetch... #{{true:'bottom', false: 'top'}[direction]} pending #{pending.length}"
+							if direction
+								if buffer.length && !shouldLoadBottom()
+									finalize rid
+								else
+									#log "appending... requested #{bufferSize} records starting from #{next}"
+									datasource.get next, bufferSize,
+									(result) ->
+										return if (rid and rid isnt ridActual) or $scope.$$destroyed
+										if result.length < bufferSize
+											eof = true
+											builder.bottomPadding(0)
+											#log "eof is reached"
+										if result.length > 0
+											clipTop()
+											for item in result
+												insert ++next, item
+											#log "appended: requested #{bufferSize} received #{result.length} buffer size #{buffer.length} first #{first} next #{next}"
+										finalize rid
+							else
+								if buffer.length && !shouldLoadTop()
+									finalize rid
+								else
+									#log "prepending... requested #{size} records starting from #{start}"
+									datasource.get first-bufferSize, bufferSize,
+									(result) ->
+										return if (rid and rid isnt ridActual) or $scope.$$destroyed
+										if result.length < bufferSize
+											bof = true
+											builder.topPadding(0)
+											#log "bof is reached"
+										if result.length > 0
+											clipBottom() if buffer.length
+											for i in [result.length-1..0]
+												insert --first, result[i]
+											#log "prepended: requested #{bufferSize} received #{result.length} buffer size #{buffer.length} first #{first} next #{next}"
+										finalize rid
+
+						# events and bindings
+
+						resizeAndScrollHandler = ->
+							if !$rootScope.$$phase && !adapter.isLoading
+								adjustBuffer()
+								$scope.$apply()
+
+						wheelHandler = (event) ->
+							scrollTop = viewport[0].scrollTop
+							yMax = viewport[0].scrollHeight - viewport[0].clientHeight
+							if (scrollTop is 0 and not bof) or (scrollTop is yMax and not eof)
+								event.preventDefault()
+
+						viewport.bind 'resize', resizeAndScrollHandler
+						viewport.bind 'scroll', resizeAndScrollHandler
+						viewport.bind 'mousewheel', wheelHandler
+
+						$scope.$watch datasource.revision, reload
+
+						if datasource.scope
+							eventListener = datasource.scope.$new()
+						else
+							eventListener = $scope.$new()
+
+						$scope.$on '$destroy', ->
+							for item in buffer
+								item.scope.$destroy()
+								item.element.remove()
+							viewport.unbind 'resize', resizeAndScrollHandler
+							viewport.unbind 'scroll', resizeAndScrollHandler
+							viewport.unbind 'mousewheel', wheelHandler
+
+
+						# adapter initializing
+
+						adapter = {}
+						adapter.isLoading = false

 						applyUpdate = (wrapper, newItems) ->
 							animations = []
@@ -456,7 +452,7 @@
 								else
 									throw new Error "applyUpdates - #{arg1} is not a valid index"
 							$q.all(animations).then ->
-								adjustBuffer(ridActual, true)
+								adjustBuffer ridActual

 						if $attr.adapter # so we have an adapter on $scope
 							adapterOnScope = getValueChain($scope, $attr.adapter)
@@ -497,15 +493,14 @@
 							adjustBuffer()

 						doInsert = (locator, item) ->
-							inserted = []
 							if angular.isFunction locator
 								throw new Error('not implemented - Insert with locator function')
 							else
 								if 0 <= locator-first-1 < buffer.length
-									inserted.push (insert locator, item)
+									insert locator, item
 									next++
 							item.scope.$index = first + i for item,i in buffer
-							adjustBuffer(null, inserted)
+							adjustBuffer()

 						eventListener.$on "insert.item", (event, locator, item)->doInsert(locator, item)
 						eventListener.$on "update.items", (event, locator, newItem)-> doUpdate(locator, newItem)


clean up copfescript syntax

clean up copfescript syntax

--- app/assets/javascripts/hanuman/conditional-logic.js.coffee
+++ app/assets/javascripts/hanuman/conditional-logic.js.coffee
@@ -82,11 +82,11 @@
     # uncheck all checkboxes
     checkboxes = container.find(":checkbox")
     checkboxes.each ->
-      $(this).prop('checked', false);
+      $(this).prop('checked', false)
     # un-select radio buttons
     radiobuttons = container.find(":radio")
     radiobuttons.each ->
-      $(this).prop('checked', false);
+      $(this).prop('checked', false)

   #evaluate conditional logic rules
   evaluateCondition: (operator, answer, value) ->


allow content to flow nicely when it's already bigger than the document.

--- app/assets/javascripts/protoadmin/layout/content.js.coffee
+++ app/assets/javascripts/protoadmin/layout/content.js.coffee
@@ -15,7 +15,11 @@
     $(window).on('resize', @resize)

   resize: =>
-    @$el.css(minHeight: $(document).height() - 300)
-    @$el.css(minHeight: $(document).height() - @top)
+    height = $(document).height()
+    if @$el.height() < height - @top
+      @$el.css(minHeight: height - 300)
+      @$el.css(minHeight: height - @top)
+    else
+      @$el.css(minHeight: 'auto')

 jQuery -> new Protoadmin.Layout.Content()


Dont send coupon code when transitioning order state

--- app/assets/javascripts/sprangular/services/checkout.coffee
+++ app/assets/javascripts/sprangular/services/checkout.coffee
@@ -34,7 +34,6 @@
         goto: goto
         order:
           use_billing: order.shipToBillAddress
-          coupon_code: order.couponCode
           ship_address_attributes: order.actualShippingAddress().serialize()
           bill_address_attributes: order.billingAddress.serialize()


Add coffee corrections

Add coffee corrections

--- BackofficeBundle/Resources/public/coffee/extendView/submitAdmin.coffee
+++ BackofficeBundle/Resources/public/coffee/extendView/submitAdmin.coffee
@@ -29,11 +29,13 @@
                   html: response
                   domContainer: $('h1.page-title').parent()
                 ))
+                $(document).scrollTop 0
               200: (response) ->
                 new viewClass(viewContext.addOption(
                   html: response
                   submitted: true
                 ))
+                $(document).scrollTop 0
           false
     return
 }


Workaround for destroying clones

Workaround for destroying clones

--- angular/core/components/document/title_form/document_title_form.coffee
+++ angular/core/components/document/title_form/document_title_form.coffee
@@ -9,7 +9,7 @@
     $scope.remove = ->
       ModalService.open ConfirmModal,
         forceSubmit: -> false
-        submit:      -> $scope.document.destroy
+        submit:      -> Records.documents.find($scope.document.id).destroy
         text:        ->
           title:    'documents_page.confirm_remove_title'
           helptext: 'documents_page.confirm_remove_helptext'


Require config when task shell starts

Require config when task shell starts

Config adds to the require paths so it needs to be required
before the handler starts so that web worker handlers have the
same require semantics as the main window.

--- src/stdlib/task-shell.coffee
+++ src/stdlib/task-shell.coffee
@@ -20,8 +20,10 @@
 # The worker's initial handler replaces itself when `start` is invoked
 self.handler =
   start: ({resourcePath, requirePath, handlerPath}) ->
+    self.resourcePath = resourcePath
     window.resourcePath = resourcePath
     importScripts(requirePath)
+    require 'config'
     self.handler = require(handlerPath)
     callTaskMethod 'started'


Account: re-enable Externals for now

Account: re-enable Externals for now

--- client/account/lib/index.coffee
+++ client/account/lib/index.coffee
@@ -142,7 +142,7 @@
         if groupSlug is 'koding'
           mergeables = section.items
         else
-          mergeables.push item  unless item.slug in [ 'Billing', 'Externals', 'Referral', 'Delete' ]
+          mergeables.push item  unless item.slug in [ 'Billing', 'Referral', 'Delete' ]

       items = items.concat mergeables


update so emitted signal matches view

update so emitted signal matches view

--- coach/src/navigation/index.cjsx
+++ coach/src/navigation/index.cjsx
@@ -40,7 +40,7 @@

   onCourseEnded: (notice) ->
     NotificationActions.acknowledge(notice)
-    channel.emit('show.registration', view: 'second-semester-registration')
+    channel.emit('show.second-semester-registration', view: 'second-semester-registration')

   render: ->
     {course} = @props


force cds view indices to be recomputed on table updates (#7036)

--- bokehjs/src/coffee/models/widgets/tables/data_table.coffee
+++ bokehjs/src/coffee/models/widgets/tables/data_table.coffee
@@ -97,6 +97,12 @@
     @connect(@model.source.change, () => @updateSelection())

   updateGrid: () ->
+    # TODO (bev) This is to enure that CDSView indices are properly computed
+    # before passing to the DataProvider. This will result in extra calls to
+    # compute_indices. This "over execution" will be addressed in a more
+    # general look at events
+    @model.view.compute_indices()
+
     @data.constructor(@model.source, @model.view)
     @grid.invalidate()
     @grid.render()


no-refresh: refresh the vm list when the account is changed

--- client/landing/app/MainApp/VirtualizationController.coffee
+++ client/landing/app/MainApp/VirtualizationController.coffee
@@ -7,8 +7,12 @@
     @dialogIsOpen = no
     @resetVMData()

-    (KD.getSingleton 'mainController').once 'AppIsReady', => @fetchVMs()
+    KD.getSingleton('mainController')
+      .once('AppIsReady', @bound 'fetchVMs')
+      .on('AccountChanged', => @emit 'VMListChanged')
+
     @on 'VMListChanged', @bound 'resetVMData'
+

   run:(options, callback = noop)->
     [callback, options] = [options, callback]  unless callback


Cleanup

Cleanup

--- plugins/github-issues/index.coffee
+++ plugins/github-issues/index.coffee
@@ -15,23 +15,17 @@
       req.auth(config.username, config.password)

   @addCommentToIssue: (config, issueNumber, comment) ->
-    console.log "Add comment"
     @githubRequest(@request.post("#{@issueUrl(config, issueNumber)}/comments"), config)
       .send({body: comment})
-      .on "error", (err) ->
-        console.log err
-      .end (res) ->
-        console.log "Success comment!"
+      .on "error", console.error
+      .end()

   @ensureIssueOpen: (config, issueNumber, callback) ->
-    console.log "Ensure issue open"
     @githubRequest(@request.patch(@issueUrl(config, issueNumber)), config)
       .send({state: "open"})
       .on "error", (err) ->
-        console.log err
         callback(err)
       .end (res) ->
-        console.log "Success open!"
         callback(res.error)

   @openIssue: (config, event, callback) ->


Bug: Dismissing Add new, then dragging variable makes two.

Fixes:
Dismissing the "add new" image dialog creates two variables when an existing image is dragged to create a new variable.

Explanation:
A callback function is registered to add a new variable when we begin the dragging of a new image icon.  Unless we remove that callback, the callback will be invoked later with a different variable, resulting in the creation of two variables.

Story:
[#153599556]
https://www.pivotaltracker.com/story/show/153599556

--- src/code/stores/image-dialog-store.coffee
+++ src/code/stores/image-dialog-store.coffee
@@ -48,6 +48,7 @@
     @resetPaletteItem()

   onClose: ->
+    @callback=null
     @close()
     @_updateChanges()


Fix merge error (extra closing parenthesis).

--- src/coffee/Deft/mvc/ViewController.coffee
+++ src/coffee/Deft/mvc/ViewController.coffee
@@ -229,7 +229,6 @@
 	###
 	getComponentSelector: ( selector ) ->
 		return @registeredComponentSelectors[ selector ]
-)

 	###*
 	@protected


Remove tooltip when draw is done

Remove tooltip when draw is done

--- app/assets/javascripts/leaflet/reactive_measure.js.coffee
+++ app/assets/javascripts/leaflet/reactive_measure.js.coffee
@@ -168,6 +168,7 @@

   removeHooks: () ->
     @_map.off 'mousemove'
+    @__tooltipMeasure.dispose()
     @__removeHooks.apply this, arguments
     return


fix FB.ui init

fix FB.ui init

--- app/assets/javascripts/sharing_tags/share/facebook.coffee
+++ app/assets/javascripts/sharing_tags/share/facebook.coffee
@@ -47,7 +47,7 @@
     @provider = @_detect_provider() if !@provider

     # todo: throw error for invalid provider
-    @constructor.init() if not FB? if @provider is 'fb_ui'
+    @constructor.init() if @provider is 'fb_ui' and not FB?

     super


Adding attributes to the Catalog service so that we can store some shareable data

--- app/assets/javascripts/sprangular/services/catalog.coffee
+++ app/assets/javascripts/sprangular/services/catalog.coffee
@@ -1,6 +1,9 @@
 Sprangular.service 'Catalog', ($http, $q, _, Status, Env) ->
   service =
     pageSize: Env.config.product_page_size
+
+    fetched:
+      taxonomies: null

     products: (search=null, page=1, options) ->
       options ||= {}
@@ -11,8 +14,10 @@
       @getPaged(page, taxon: path)

     taxonomies: ->
+      _service = @
       $http.get("/api/taxonomies")
         .then (response) ->
+          _service.fetched.taxonomies = response.data
           response.data

     taxonsByName: (name) ->


add active add date as state

add active add date as state

--- src/components/course-calendar/month.cjsx
+++ src/components/course-calendar/month.cjsx
@@ -30,6 +30,7 @@

   getInitialState: ->
     date: @props.startDate or moment()
+    activeAddDate: null

   setDate: (date) ->
     unless moment(date).isSame(@state.date, 'month')
@@ -63,7 +64,9 @@

   handleClick: (componentName, dayMoment, mouseEvent) ->
     @refs.addOnDay.updateState(dayMoment, mouseEvent.pageX, mouseEvent.pageY)
-    mouseEvent.currentTarget.classList.add('active')
+    @setState({
+      activeAddDate: dayMoment
+    })

   checkAddOnDay: (componentName, dayMoment, mouseEvent) ->
     unless mouseEvent.relatedTarget is React.findDOMNode(@refs.addOnDay)
@@ -75,7 +78,9 @@

   hideAddOnDay: (componentName, dayMoment, mouseEvent) ->
     @refs.addOnDay.close()
-    document.querySelector('.active.rc-Day')?.classList.remove('active')
+    @setState({
+      activeAddDate: null
+    })

   # render days based on whether they are past or upcoming
@@ -85,17 +90,31 @@

     durationDays = calendarDuration.iterate('days')
     days = []
+    hasActiveAddDate =  @state.activeAddDate?
+
     while durationDays.hasNext()
       dayIter = durationDays.next()
+
       if dayIter.isAfter(referenceDay, 'day')
+
         day = <Day
           date={dayIter}
           onClick={@handleClick}
-          onMouseLeave={@checkAddOnDay}
-          onMouseEnter={@undoActives}
           modifiers={{upcoming: true}}/>
+
+        if hasActiveAddDate
+          # Only attach hover event check when there is an active date.
+          # Otherwise, we would be rendering way too often.
+          day.props.onMouseLeave = @checkAddOnDay
+          day.props.onMouseEnter = @undoActives
+
+          if @state.activeAddDate.isSame(dayIter, 'day')
+            day.props.classes =
+              active: true
+
       else
         day = <Day date={dayIter} modifiers={{past: true}}/>
+
       days.push(day)

     days


Only read component size if mounted

Only read component size if mounted

--- src/components/resize-listener-mixin.cjsx
+++ src/components/resize-listener-mixin.cjsx
@@ -40,12 +40,13 @@
     {width, height}

   _getComponentSize: ->
+    return {height: 0, width: 0} unless @isMounted()
     componentNode = @getDOMNode()
-
     width: componentNode.offsetWidth
     height: componentNode.offsetHeight

   setInitialSize: ->
+    return unless @isMounted()
     windowEl = @_getWindowSize()
     componentEl = @_getComponentSize()


Delete subscriptions.coffee

Delete subscriptions.coffee

--- actioncable/app/assets/javascripts/action_cable/subscriptions.coffee
+++ actioncable/app/assets/javascripts/action_cable/subscriptions.coffee
@@ -1,66 +0,0 @@
-# Collection class for creating (and internally managing) channel subscriptions. The only method intended to be triggered by the user
-# us ActionCable.Subscriptions#create, and it should be called through the consumer like so:
-#
-#   @App = {}
-#   App.cable = ActionCable.createConsumer "ws://example.com/accounts/1"
-#   App.appearance = App.cable.subscriptions.create "AppearanceChannel"
-#
-# For more details on how you'd configure an actual channel subscription, see ActionCable.Subscription.
-class ActionCable.Subscriptions
-  constructor: (@consumer) ->
-    @subscriptions = []
-
-  create: (channelName, mixin) ->
-    channel = channelName
-    params = if typeof channel is "object" then channel else {channel}
-    subscription = new ActionCable.Subscription @consumer, params, mixin
-    @add(subscription)
-
-  # Private
-
-  add: (subscription) ->
-    @subscriptions.push(subscription)
-    @consumer.ensureActiveConnection()
-    @notify(subscription, "initialized")
-    @sendCommand(subscription, "subscribe")
-    subscription
-
-  remove: (subscription) ->
-    @forget(subscription)
-    unless @findAll(subscription.identifier).length
-      @sendCommand(subscription, "unsubscribe")
-    subscription
-
-  reject: (identifier) ->
-    for subscription in @findAll(identifier)
-      @forget(subscription)
-      @notify(subscription, "rejected")
-      subscription
-
-  forget: (subscription) ->
-    @subscriptions = (s for s in @subscriptions when s isnt subscription)
-    subscription
-
-  findAll: (identifier) ->
-    s for s in @subscriptions when s.identifier is identifier
-
-  reload: ->
-    for subscription in @subscriptions
-      @sendCommand(subscription, "subscribe")
-
-  notifyAll: (callbackName, args...) ->
-    for subscription in @subscriptions
-      @notify(subscription, callbackName, args...)
-
-  notify: (subscription, callbackName, args...) ->
-    if typeof subscription is "string"
-      subscriptions = @findAll(subscription)
-    else
-      subscriptions = [subscription]
-
-    for subscription in subscriptions
-      subscription[callbackName]?(args...)
-
-  sendCommand: (subscription, command) ->
-    {identifier} = subscription
-    @consumer.send({command, identifier})


fix croppable image template fetch

fix croppable image template fetch

--- app/assets/javascripts/ab_admin/components/croppable_image.js.coffee
+++ app/assets/javascripts/ab_admin/components/croppable_image.js.coffee
@@ -28,5 +28,5 @@
     $asset = $("#asset_#{asset_id}")
     geometry = [@cropData['w'], @cropData['h'], @cropData['x'], @cropData['y']].join(',')
     $.post "/admin/assets/#{$asset.data('id')}/crop", {geometry: geometry}, (data) =>
-      $asset.replaceWith @el.data('AdminAssets').template(data.asset)
+      $asset.replaceWith @el.data('assets').template(data.asset)
       $.fancybox.close()


Fix issue where 0-point tiers were not grading or saving properly on rubric re-grade

--- app/assets/javascripts/angular/controllers/GradeRubricCtrl.js.coffee
+++ app/assets/javascripts/angular/controllers/GradeRubricCtrl.js.coffee
@@ -350,7 +350,7 @@
     this.badges = {}
     this.availableBadges = angular.copy($scope.courseBadges)
     this.loadTierBadges(attrs["tier_badges"]) if attrs["tier_badges"] #add badges if passed on init
-    this.points = attrs.points || null
+    this.points = attrs.points || 0
     this.description = attrs.description or ""
     this.resetChanges()
   TierPrototype.prototype =


Fix Timeline step size (js)

Fix Timeline step size (js)

--- app/assets/javascripts/martian_components/components/timeline.coffee
+++ app/assets/javascripts/martian_components/components/timeline.coffee
@@ -17,21 +17,22 @@
     @initSlider()

   initNavSlider: =>
-    yearsEl     = @navSlider.find('.years')
-    yearsValues = yearsEl.data('values')
+    @yearsEl           = @navSlider.find('.years')
+    @yearsValues       = @yearsEl.data('values')
+    @navSliderStepSize = (100 / (@yearsValues.length - 1))

-    yearsValues.each (item, index) ->
+    @yearsValues.each (item, index) =>
       year = $("
#{item}
")
-      year.css('left', (100 / (yearsValues.length - 1) * index) + '%')
-      year.appendTo yearsEl
+      year.css('left', (@navSliderStepSize * index) + '%')
+      year.appendTo @yearsEl

     @navSlider.slider
       values: [0]
-      step:   yearsValues.length - 1
+      step:   @navSliderStepSize

     @navSlider.on 'slide', (ev, ui) =>
       @slider.find('.slick-track')[0].style.webkitAnimationPlayState = 'paused'
-      @slider.slickGoTo(ui.value / 10)
+      @slider.slickGoTo(ui.value / @navSliderStepSize)

   initSlider: =>
     @slider.slick
@@ -46,4 +47,4 @@
         }
       ]
       onBeforeChange: (slider, current, next) =>
-        @navSlider.slider('values', 0, next * 10)
+        @navSlider.slider('values', 0, next * @navSliderStepSize)


populate root recursively

populate root recursively

--- gulp-nav.coffee
+++ gulp-nav.coffee
@@ -138,11 +138,11 @@
     parent:
       enumerable: yes             # these properties should be easy to find
       get: ->                     # they're accessors because we need lazy eval
-        navInContext nav.parent, context.concat postFix
+        navInContext nav.parent, context.concat(postFix), root
     children:
       enumerable: yes
       get: ->
-        (navInContext child, context.concat name for [child, name] in (
+        (navInContext child, context.concat(name), root for [child, name] in (
           [child, name] for name, child of nav.children)
             .sort ([a, ...], [b, ...]) -> a.order - b.order)
     siblings:
@@ -152,4 +152,4 @@
     root:
       enumerable: yes
       get: ->
-        navInContext root.obj, context.concat root.name
+        navInContext root.obj, context.concat(root.name), root


Add express/gulp url for serve plugins directory in development server.

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -215,6 +215,7 @@
     app.use("/images", express.static("#{__dirname}/dist/images"))
     app.use("/partials", express.static("#{__dirname}/dist/partials"))
     app.use("/fonts", express.static("#{__dirname}/dist/fonts"))
+    app.use("/plugins", express.static("#{__dirname}/dist/plugins"))

     app.all "/*", (req, res, next) ->
         # Just send the index.html for other files to support HTML5Mode


Remove deprecated gulp.run() calls

Remove deprecated gulp.run() calls

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -10,37 +10,58 @@
 app_dir    = 'app'
 public_dir = app_dir + '/public'

-gulp.task 'web-db', ->
+web_db = ->
   gulp.src 'src/client/db/**'
   .pipe gulp.dest app_dir + '/db'

-gulp.task 'web-resources', ->
+web_resources = ->
   gulp.src 'src/client/resources/**'
   .pipe gulp.dest public_dir

-gulp.task 'web-coffee', ->
+web_coffee = ->
   gulp.src 'src/client/*.coffee'
     .pipe coffee    bare: true
     .pipe concat    'jitterbug-client.js'
     .pipe gulp.dest public_dir

-gulp.task 'web-style', ->
+web_style = ->
   gulp.src 'src/client/*.scss'
     .pipe sass().on 'error', sass.logError
     .pipe concat    'jitterbug-client.css'
     .pipe gulp.dest public_dir + '/css'

-gulp.task 'server-coffee', ->
+server_coffee = ->
   gulp.src 'src/server/*.coffee'
     .pipe coffee    bare: true
     .pipe gulp.dest app_dir

-gulp.task 'libs', ->
+libs = ->
   gulp.src main_bf()
     .pipe filter '*.js'
     .pipe concat 'libs.min.js'
     .pipe uglify()
     .pipe gulp.dest public_dir
+
+quick_build = ->
+  web_resources()
+  web_db()
+  web_coffee()
+  web_style()
+  server_coffee()
+
+full_build = ->
+  libs()
+  quick_build()
+
+gulp.task 'web-db',        -> web_db()
+gulp.task 'web-resources', -> web_resources()
+gulp.task 'web-coffee',    -> web_coffee()
+gulp.task 'web-style',     -> web_style()
+gulp.task 'server-coffee', -> server_coffee()
+gulp.task 'libs',          -> libs()
+gulp.task 'quick-build',   -> quick_build()
+gulp.task 'full-build',    -> full_build()
+gulp.task 'default',       -> full_build()

 gulp.task 'start', ['quick-build'], ->
   nodemon
@@ -49,12 +70,3 @@
     tasks: ['quick-build']
     env:
       'NODE_ENV': 'development'
-
-gulp.task 'quick-build', ->
-  gulp.run   'web-resources', 'web-db', 'web-coffee', 'web-style', 'server-coffee'
-
-gulp.task 'full-build', ->
-  gulp.run   'libs', 'quick-build'
-
-gulp.task 'default', ->
-  gulp.run   'full-build'


Do not push automatically

Do not push automatically

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -63,6 +63,6 @@
   current = branch()
   git.checkout 'master'
   git.merge current
-  shell.task ["gulp tag"]
+  #shell.task ["gulp tag"]
   git.checkout current


Repair error,update gulpfile

Repair error,update gulpfile

 这里gulp.src()里面的数组元素hook-duoshuo.js后面少了一个逗号，会构建失败,加上即可

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -6,7 +6,7 @@
   return gulp.src([
     './source/js/src/utils.js',
     './source/js/src/motion.js',
-    './source/js/src/hook-duoshuo.js'
+    './source/js/src/hook-duoshuo.js',
     './source/js/src/bootstrap.js',
     './source/js/src/post-details.js',
     './source/js/src/schemes/pisces.js'


add table of pure-css

add table of pure-css

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -144,6 +144,7 @@
         purecss/build/pure-min.css
         purecss/build/grids-responsive-min.css
         purecss/build/buttons-min.css
+        purecss/build/tables-min.css

         github-fork-ribbon-css/gh-fork-ribbon.css
     '


change webp image quality from 80 to 90

change webp image quality from 80 to 90

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -264,7 +264,7 @@
     .pipe plumber()
     .pipe size()
     .pipe webp
-      quality: 80
+      quality: 90
     .pipe size()
     .pipe gulp.dest('./')


Fix build

Fix build

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -86,7 +86,7 @@
   zip.extractAllTo dir, true

 gulp.task 'copy-files', ['download-electron'], ->
-  gulp.src(['app.coffee', 'bower.json', 'default-config.cson', 'index.html', 'index.js', 'LICENSE', 'package.json'])
+  gulp.src(['app.coffee', 'bower.json', 'default-config.cson', 'constant.cson', 'index.html', 'index.js', 'LICENSE', 'package.json'])
       .pipe(gulp.dest(BUILD_ROOT))
   gulp.src(['assets/**/*']).pipe(gulp.dest(path.join(BUILD_ROOT, 'assets')))
   gulp.src(['components/**/*']).pipe(gulp.dest(path.join(BUILD_ROOT, 'components')))


➖Delete a gulpfile.coffee

➖Delete a gulpfile.coffee

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -1,16 +0,0 @@
-gulp       = require 'gulp'
-browserify = require 'browserify'
-babelify   = require 'babelify'
-source     = require 'vinyl-source-stream'
-
-gulp.task 'browserify', ()->
-  browserify entries: [ './src/Taiyaki.es6' ], extensions: [ 'es6' ]
-  .transform babelify
-  .bundle()
-  .pipe source 'taiyaki.js'
-  .pipe gulp.dest './build/Release/'
-
-gulp.task 'watch', ()->
-  gulp.watch 'src/**/*.es6', ['browserify']
-
-gulp.task 'default', [ 'browserify', 'watch' ]


gulp file now prints some logs

gulp file now prints some logs

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -29,7 +29,7 @@

 # global variables

-env = if $.util.env.mode then $.util.env.mode else 'development'
+env = if $.util.env.mode? then $.util.env.mode else 'development'
 compressed = env == 'production'
 debug = $.util.env.debug?
 paths =
@@ -37,6 +37,14 @@
   web: 'src/main/web'
   build: 'build'
 reload = browserSync.reload
+
+
+# some prints
+
+console.log 'Build in ' + env + ' mode.'
+console.log 'Debug is ' + (if debug then 'enabled' else 'disabled') + '.'
+console.log 'Paths are : '
+console.log paths

 # preprocessing tasks
@@ -131,12 +139,14 @@

 # clean tasks

-gulp.task 'clean', ['clean:before-build'], ->
+gulp.task 'clean', ['clean:before-build'], (cb) ->
+  rm [
+    '*.log'
+  ], cb

 gulp.task 'clean:before-build', (cb) ->
   rm [
     'build'
-    '*.log'
   ], cb

 gulp.task 'clean:after-build', (cb) ->


updated to v0.0.69

updated to v0.0.69

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -74,20 +74,4 @@

 #$$.task 'y', ->

-$$.task 'z', co ->
-
-  base = '~/OneDrive/密钥/Anitama/www.anitama.cn'
-  host = '118.178.128.8'
-
-  yield $$.ssh.connect
-    host: host
-    port: 22
-    username: 'root'
-    privateKey: yield $$.read "#{base}/privateKey.txt"
-
-  yield $$.ssh.shell [
-    'cd /doremi'
-    'll'
-  ]
-
-  yield $$.ssh.disconnect()
+#$$.task 'z', co ->


Use source-map instead of eval

Use source-map instead of eval

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -18,7 +18,7 @@
 gulp.task 'webpack-dev-server', (callback) ->
   # modify some webpack config options
   conf = Object.create webpackConfig
-  conf.devtool = 'eval'
+  conf.devtool = 'source-map'
   conf.debug = true

   # Start a webpack-dev-server


Commit yarn_log dig, doesn't make sense

Commit yarn_log dig, doesn't make sense

--- hdp/hdfs.coffee
+++ hdp/hdfs.coffee
@@ -124,16 +124,17 @@
       modified = true if created
       do_log()
   do_log = ->
-    ctx.log "Create hdfs and mapred log: #{hdfs_log_dir}"
-    ctx.mkdir
-      destination: "#{yarn_log_dir}/#{yarn_user}"
-      uid: yarn_user
-      gid: hadoop_group
-      mode: 0o755
-    , (err, created) ->
-      return next err if err
-      modified = true if created
-      do_pid()
+    do_pid()
+    # ctx.log "Create hdfs and mapred log: #{hdfs_log_dir}"
+    # ctx.mkdir
+    #   destination: "#{yarn_log_dir}/#{yarn_user}"
+    #   uid: yarn_user
+    #   gid: hadoop_group
+    #   mode: 0o755
+    # , (err, created) ->
+    #   return next err if err
+    #   modified = true if created
+    #   do_pid()
   do_pid = ->
     ctx.log "Create hdfs and mapred pid: #{hdfs_pid_dir} with owner #{hdfs_user}:#{hadoop_group}"
     ctx.mkdir
@@ -281,7 +282,6 @@
     mode: 0o755
   , (err, created) ->
     ctx.log 'Creating HTTP Principals and SPNEGO keytab'
-    #if ctx.config.hdp.namenode or ctx.config.hdp.datanode or ctx.config.hdp.secondary_namenode or ctx.config.hdp.oozie or ctx.config.hdp.webhcat
     ctx.krb5_addprinc
       principal: "HTTP/#{ctx.config.host}@#{realm}"
       randkey: true


Replace inline button with framed button implemented with ControlIframe

--- js-library/app/js/jail_iframe/classes/buttons.coffee
+++ js-library/app/js/jail_iframe/classes/buttons.coffee
@@ -1,27 +1,41 @@
 class Button
   constructor: (dom_events={}) ->
-    @$el = $(@content)
-    @$el.appendTo(FactlinkJailRoot.$factlinkCoreContainer)
+    @frame = new FactlinkJailRoot.ControlIframe()
+    @frame.doc.body.innerHTML = @content
+    el = @el=  @frame.doc.body.firstChild
     for event, callback of dom_events
-      @$el.bind event, callback
+      el.addEventListener event, callback
+    @frame.resizeFrame()
+    @$el = $(el)

-  startLoading: => @$el.addClass    "fl-loading"
-  stopLoading:  => @$el.removeClass "fl-loading"
+
+  startLoading: => @$el.addClass "fl-loading"
+  stopLoading:  => @$el.removeClass  "fl-loading"

   setCoordinates: (top, left) =>
-    return if @$el.hasClass 'active'
-    FactlinkJailRoot.set_position_of_element top, left, window, @$el
+#    return if @$el.hasClass 'active'
     console.log 'setting position'
+    FactlinkJailRoot.set_position_of_element top, left, window, @frame.$el

   show: =>
     @stopLoading()
-    FactlinkJailRoot.$factlinkCoreContainer.find('div.fl-button').removeClass('active')
     console.log @el.className
+    #TODO:what's this line do?
+    #FactlinkJailRoot.$factlinkCoreContainer.find('div.fl-button').removeClass('active')
     @$el.addClass 'active been-active'
+    @frame.$el.addClass 'factlink-frame-visible'
+    console.log @el.className

-  hide: => @$el.removeClass 'active'

-  destroy: => @$el.remove()
+  hide: =>
+    @$el.removeClass 'active'
+    @frame.$el.removeClass 'factlink-frame-visible'
+    console.log 'hiding frame'
+
+
+  destroy: =>
+    @frame.destroy()
+    console.log 'destroying frame'

 class FactlinkJailRoot.ShowButton extends Button


revert the last one, it was a mistake

revert the last one, it was a mistake

--- library/exposure/navigate.coffee
+++ library/exposure/navigate.coffee
@@ -90,7 +90,7 @@
         attaching = "no hasher library has been found"
         assert _.isObject(hasher or null), attaching
         assert _.isObject(crossroads or null), router
-        logger.info "Setting up the hashing navigation"
+        logger.info "setting up the hashing navigation"
         parser = (landed, old) -> crossroads.parse landed
         begin = _.find @, (x) -> x?.meta?.options?.default
         hasher.setHash begin.meta.endpoint if begin?.meta
@@ -101,5 +101,5 @@
             return unless _.isFunction value or null
             return unless value?.meta?.endpoint or 0
             assert endpoint = try value.meta.endpoint
-            logger.debug "Mount endpoint #{endpoint}"
+            logger.debug "mount endpoint #{endpoint}"
             crossroads.addRoute "#{endpoint}", value


Change hash from md5 to sha1

Change hash from md5 to sha1

--- library/membrane/securing.coffee
+++ library/membrane/securing.coffee
@@ -69,9 +69,9 @@
     # Please be sure invoke the `next` arg to proceed, if relevant.
     headers: (request, response, resource, domain, next) ->
         return next() unless response.statusCode is 200
-        md5 = -> require("crypto").createHash("md5")
+        sha1 = -> require("crypto").createHash "sha1"
         key = (x) -> "securing:rduplex:token:dynamic:#{x}"
-        gen = (u) -> md5().update("#{@uuid}-#{u}").digest("hex")
+        gen = (u) -> sha1().update("#{@uuid}-#{u}").digest("hex")
         internal = (e) -> "internal Redis error: #{e}"
         noUuid = "the request has not UUID attached"
         assert _.isString(u = request.uuid), noUuid
@@ -86,9 +86,9 @@
     # place to implementation various schemes for authorization. If
     # you wish to decline, just don't call `next` and close socket.
     screening: (context, socket, binder, next) ->
-        md5 = -> require("crypto").createHash("md5")
+        sha1 = -> require("crypto").createHash "sha1"
         key = (x) -> "securing:rduplex:token:dynamic:#{x}"
-        gen = (u) -> md5().update("#{@uuid}-#{u}").digest("hex")
+        gen = (u) -> sha1().update("#{@uuid}-#{u}").digest("hex")
         internal = (e) -> "internal Redis error: #{e}"
         noUuid = "the context has no UUID attached"
         assert uuid = binder.uuid.request, noUuid


fix lib/css file concatenation

fix lib/css file concatenation

the semicolon was breaking/invalidating stylesheets

--- lib/frontend/asset/utils.coffee
+++ lib/frontend/asset/utils.coffee
@@ -29,7 +29,7 @@
         util.log "\x1B[1;31mError: Unable to compile CoffeeScript file #{path} to JS\x1B[0m"
         throw new Error(e)
     output = exports.minifyJS(file_name, output) if file_name.match(/\.(coffee|js)/) and !file_name.match(/\.min/)
-    output += ';' # Ensures the file ends with a semicolon. Many libs don't and would otherwise break when concatenated
+    output += ';' if file_name.match(/\.js/) # Ensures the file ends with a semicolon. Many libs don't and would otherwise break when concatenated
     output
   .join("\n")


FIX: clipping for RectangleElement

FIX: clipping for RectangleElement

--- source/Art/Engine/Elements/Shapes/RectangleElement.coffee
+++ source/Art/Engine/Elements/Shapes/RectangleElement.coffee
@@ -1,12 +1,11 @@
-Foundation = require 'art-foundation'
 Atomic = require 'art-atomic'
 Text = require 'art-text'
 ShadowableElement = require '../ShadowableElement'
 {Paths} = require 'art-canvas'
-{pureMerge, floatEq, AtomElement, createWithPostCreate, isPlainObject, isNumber} = Foundation
+{pureMerge, floatEq, log, AtomElement, defineModule, isPlainObject, isNumber} = require 'art-standard-lib'
 {rectanglePath} = Paths

-module.exports = createWithPostCreate class RectangleElement extends ShadowableElement
+defineModule module, class RectangleElement extends ShadowableElement

   @drawProperty
     radius:
@@ -30,11 +29,13 @@
   # Custom Clipping
   # override to support rounded-rectangle clipping
   #####################
+  clipOptions = radius: 0
   _drawWithClipping: (clipArea, target, elementToTargetMatrix)->
     if floatEq @_radius, 0
       super
     else
-      lastClippingInfo = target.openClipping rectanglePath, elementToTargetMatrix, target.pixelSnapRectangle(elementToTargetMatrix, @getPaddedArea()), @_radius
+      clipOptions.radius = @_radius
+      lastClippingInfo = target.openClipping rectanglePath, elementToTargetMatrix, @paddedArea, clipOptions
       @_drawChildren target, elementToTargetMatrix
       target.closeClipping lastClippingInfo


components-gtk: LoadPixbuf: wrap data into JS object

--- components-gtk/LoadPixbuf.coffee
+++ components-gtk/LoadPixbuf.coffee
@@ -22,7 +22,7 @@
   , (data, groups, out) ->
     try
       loader = new GdkPixbuf.PixbufLoader
-      loader.write_bytes data
+      loader.write_bytes data.data
       loader.close()
       out.send loader.get_pixbuf()
     catch e


Handle replacement data clearing in the pane

--- lib/project/results-pane.coffee
+++ lib/project/results-pane.coffee
@@ -49,6 +49,7 @@
   handleEvents: ->
     @subscribe @model, 'search', @onSearch
     @subscribe @model, 'cleared', @onCleared
+    @subscribe @model, 'replacement-state-cleared', @onReplacementStateCleared
     @subscribe @model, 'finished-searching', @onFinishedSearching
     @subscribe @model, 'paths-searched', @onPathsSearched

@@ -80,5 +81,8 @@
   onFinishedSearching: (results) =>
     @previewCount.html(Util.getResultsMessage(results))

+  onReplacementStateCleared: (results) =>
+    @previewCount.html(Util.getResultsMessage(results))
+
   onCleared: =>
     @previewCount.text('Find in project results')


Environments: Since the new router is not waiting for anything, we need to wait for maincontroller's ready to avoid race conditions

--- client/Environments/views/environmentsmainscene.coffee
+++ client/Environments/views/environmentsmainscene.coffee
@@ -53,7 +53,7 @@
     paymentControl.on "SubscriptionCompleted", ->
       freePlanView.updatePartial ""

-    @fetchStacks()
+    KD.singletons.mainController.ready => @fetchStacks()

   fetchStacks: ->
     EnvironmentDataProvider.get (@environmentData) =>


activityticker : comment view added.

activityticker : comment view added.

--- client/Social/Activity/views/activitytickeritem.coffee
+++ client/Social/Activity/views/activitytickeritem.coffee
@@ -177,6 +177,28 @@
     return "{{> @avatar}}
{{> @actor}} posted {{> @subj}}
"

+class ActivityTickerUserCommentItem extends ActivityTickerBaseItem
+  constructor: (options = {}, data) ->
+    super options, data
+    {@source, @target} = data
+
+    @avatar    = new AvatarView
+      size     : width: 30, height: 30
+      cssClass : "avatarview"
+    , @target
+
+    @origin   = new ProfileLinkView null, @target
+    @subj     = new ActivityLinkView null, @source
+
+  pistachio: ->
+    """
+    {{> @avatar}}
+

+      #{if @target.getId() is KD.whoami().getId() then "You" else @origin } commented on {{> @subj}}
+

+    """
+
+
 class ActivityTickerItem extends KDListItemView
   itemClassMap =
     "JGroup_member_JAccount"           : ActivityTickerMemberItem


MainTabView: Fixed router.back issue on main tabview.

--- client/landing/app/MainApp/maintabs/maintabview.coffee
+++ client/landing/app/MainApp/maintabs/maintabview.coffee
@@ -78,8 +78,15 @@
     # to show the previousPane when a pane
     # is removed, that's why we override it to use
     # kodingrouter
+
+    index        = @getPaneIndex pane
+    visibles     = @getVisibleTabs()
+    visibleIndex = visibles.indexOf pane
+    leftPane     = visibles[visibleIndex - 1]
+    rightPane    = visibles[visibleIndex + 1]
+
     pane.emit "KDTabPaneDestroy"
-    index = @getPaneIndex pane
+
     isActivePane = @getActivePane() is pane
     @panes.splice index, 1
     pane.destroy()
@@ -87,13 +94,13 @@
     @handles.splice index, 1
     handle.destroy()
     @emit "PaneRemoved"
-    if isActivePane
-      if prevPane = @getPaneByIndex @lastOpenPaneIndex
-        appInstance = @appManager.getByView prevPane.mainView
-        @appManager.showInstance appInstance
-      else
-        @router.back()

+    if rightPane
+      @appManager.showInstance @appManager.getByView rightPane.mainView
+    else if leftPane
+      @appManager.showInstance @appManager.getByView leftPane.mainView
+    else
+      @router.handleRoute "/Activity"

   createTabPane:(options = {}, mainView)->


Ensure that test bindings are always removed

--- client/test/src/views/data_origin_selector_view.coffee
+++ client/test/src/views/data_origin_selector_view.coffee
@@ -41,18 +41,19 @@

   view.$el.find("li[value='kittens']").trigger('click')

-  assert.isTrue(
-    selectedSpy.calledOnce,
-    "Expected selectedSpy to be called once but was called
-      #{selectedSpy.callCount} times"
-  )
+  try
+    assert.isTrue(
+      selectedSpy.calledOnce,
+      "Expected selectedSpy to be called once but was called
+        #{selectedSpy.callCount} times"
+    )

-  assert.isTrue(
-    selectedSpy.calledWith('kittens'),
-    "Expected the event to be triggered with the origin name"
-  )
-
-  Backbone.off('indicator_selector:data_origin:selected')
+    assert.isTrue(
+      selectedSpy.calledWith('kittens'),
+      "Expected the event to be triggered with the origin name"
+    )
+  finally
+    Backbone.off('indicator_selector:data_origin:selected')
 )

 test("When 'All sources' is selected, the view triggers a 'selected' event with
@@ -70,16 +71,17 @@
   $(view.$el.find("option")[0]).prop("selected", true)
   view.$el.find("select").trigger('change')

-  assert.isTrue(
-    selectedSpy.calledOnce,
-    "Expected selectedSpy to be called once but was called
-      #{selectedSpy.callCount} times"
-  )
+  try
+    assert.isTrue(
+      selectedSpy.calledOnce,
+      "Expected selectedSpy to be called once but was called
+        #{selectedSpy.callCount} times"
+    )

-  assert.isTrue(
-    selectedSpy.calledWith(undefined),
-    "Expected the event to be triggered with no origin name"
-  )
-
-  Backbone.off('indicator_selector:data_origin:selected')
+    assert.isTrue(
+      selectedSpy.calledWith(undefined),
+      "Expected the event to be triggered with no origin name"
+    )
+  finally
+    Backbone.off('indicator_selector:data_origin:selected')
 )


Set repo tmpl attributes using the actual attributes
from the repo model.

Moved application of draggable/droppable code
until after the repo list is completely rendered.

--- frontend/coffeescript/app/dashboard/views.coffee
+++ frontend/coffeescript/app/dashboard/views.coffee
@@ -31,20 +31,20 @@
                     <%= privacy_icon %>

-                    <a href='<%= webform %>' class='btn btn-small'>
+                    <a href='<%= webform_uri %>' class='btn btn-small'>
                          Add Data

-                    <a href='<%= repo_url %>'>
-                        <%= repo_name %>
+                    <a href='<%= uri %>'>
+                        <%= name %>

-                            <%= repo_description %>
+                            <%= description %>

-                    <%= repo_submissions %>
+                    <%= submissions %>

''' )

@@ -119,45 +119,45 @@
                 if repo.get( 'org' )
                     filters.push( 'shared' )

-                repo_el = repo_tmpl(
-                            id: repo.get( 'id' )
-                            filters: filters.join( ' ' )
-                            privacy_icon: privacy_icon
-                            webform: repo.get( 'webform_uri' )
-                            repo_url: repo.get( 'uri' )
-                            repo_name: repo.get( 'name' )
-                            repo_description: repo.get( 'description' )
-                            repo_submissions: repo.get( 'submissions' ) )
+                # Copy the repo metadata into a new object
+                repo_attrs = $.extend( true, {}, repo.attributes )
+                # Add the additional bits of metadata we need to do filters and
+                # show off the fancy privacy icon
+                repo_attrs[ 'filters' ] = filters.join( ' ' )
+                repo_attrs[ 'privacy_icon' ] = privacy_icon

+                # Create the repo HTML and add it to the DOM
+                repo_el = repo_tmpl( repo_attrs )
                 @repo_list.append( repo_el )

-                $( "#repo_list tr" ).draggable(
-                    helper: 'clone'
-                    opacity: 0.7
+            # Apply draggable/droppable attributes to the new repo rows.
+            $( "#repo_list tr" ).draggable(
+                helper: 'clone'
+                opacity: 0.7
+            )
+
+            $( "#studies li" ).droppable(
+                hoverClass: 'drop-hover'
+                drop: ( event, ui ) ->
+                    study_id = $( 'a', @ ).data( 'study' )
+                    if not study_id?
+                        study_id = null
+
+                    repo_id = $( ui.draggable ).data( 'repo' )
+
+                    console.log( "Moving #{repo_id} to #{study_id}" )
+
+                    $.ajax(
+                        headers:
+                            'Accept' : 'application/json'
+                            'Content-Type' : 'application/json'
+                        url: "/api/v1/repos/#{repo_id}"
+                        type: 'PATCH',
+                        data: JSON.stringify( { 'study': study_id } )
+                        success: ( response, textStatus, jqXhr ) ->
+                            console.log( response )
+                    )
                 )
-
-                $( "#studies li" ).droppable(
-                    hoverClass: 'drop-hover'
-                    drop: ( event, ui ) ->
-                        study_id = $( 'a', @ ).data( 'study' )
-                        if not study_id?
-                            study_id = null
-
-                        repo_id = $( ui.draggable ).data( 'repo' )
-
-                        console.log( "Moving #{repo_id} to #{study_id}" )
-
-                        $.ajax(
-                            headers:
-                                'Accept' : 'application/json'
-                                'Content-Type' : 'application/json'
-                            url: "/api/v1/repos/#{repo_id}"
-                            type: 'PATCH',
-                            data: JSON.stringify( { 'study': study_id } )
-                            success: ( response, textStatus, jqXhr ) ->
-                                console.log( response )
-                        )
-                    )

             @_apply_filters()


Move tooltip placement deduction to a function

--- lib/tool-bar-button-view.coffee
+++ lib/tool-bar-button-view.coffee
@@ -12,17 +12,9 @@

     if options.tooltip
       @prop 'title', options.tooltip
-      toolbarPosition = atom.config.get('tool-bar.position')
-      tooltipPlacement = (toolbarPosition is "Top")    and "bottom" or
-                         (toolbarPosition is "Right")  and "left"   or
-                         (toolbarPosition is "Bottom") and "top"    or
-                         (toolbarPosition is "Left")   and "right"
-      @subscriptions.add atom.tooltips.add(
-        this,
-        {
-          title: options.tooltip
-          placement: tooltipPlacement
-        }
+      @subscriptions.add atom.tooltips.add(this,
+        title: options.tooltip
+        placement: @getTooltipPlacement
       )

     if options.iconset
@@ -58,3 +50,11 @@
   storeFocusedElement: ->
     if not document.activeElement.classList.contains 'tool-bar-btn'
       @previouslyFocusedElement = document.activeElement
+
+  getTooltipPlacement: ->
+    toolbarPosition = atom.config.get 'tool-bar.position'
+    return toolbarPosition is "Top"    and "bottom" or
+           toolbarPosition is "Right"  and "left"   or
+           toolbarPosition is "Bottom" and "top"    or
+           toolbarPosition is "Left"   and "right"
+


fix selection of prerender pages in pdf viewer

--- services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee
+++ services/web/public/coffee/ide/pdfng/directives/pdfViewer.coffee
@@ -265,13 +265,13 @@
 					lastVisiblePage = visiblePages[len-1].pageNum
 					lastVisiblePageIdx = lastVisiblePage - 1
 					# first page after
-					if lastVisiblePageIdx + 1 < len
+					if lastVisiblePageIdx + 1 < scope.pages.length
 						extra.push scope.pages[lastVisiblePageIdx + 1]
 					# page before
 					if firstVisiblePageIdx > 0
 						extra.push scope.pages[firstVisiblePageIdx - 1]
 					# second page after
-					if lastVisiblePageIdx + 2 < len
+					if lastVisiblePageIdx + 2 < scope.pages.length
 						extra.push scope.pages[lastVisiblePageIdx + 2]
 					return visiblePages.concat extra


Add healthcare check to the publisher

Add healthcare check to the publisher

--- library/exposure/publish.coffee
+++ library/exposure/publish.coffee
@@ -68,6 +68,7 @@
             return reject "wrong body" unless body and _.isArray body
             return reject "no service" unless id = _.find body, mirror
             return reject "no GET" unless get = _.find id.methods, method
+            return reject "no healthcare" unless _.isObject id.healthcare
             return reject "no relevants" unless get.relevant.length is 2
             return reject "no markings" unless get.markings.framework?
             return reject "no githubs" unless get.github.length is 1


slight change of names

slight change of names

--- library/membrane/transit.coffee
+++ library/membrane/transit.coffee
@@ -126,7 +126,7 @@
     # emits a modified statement instead of bare remote symbol ref.
     # This statement invokes the specific reconfiguration routine.
     # Please see the `Widget` class implementation for an exmaple.
-    @reconfigured: (signature) ->
+    @reconfigure: (signature) ->
         message = "Set reconfiguration of %s in %s"
         assert remotes = this.remotes or new Array()
         assert previous = @considerations or new Array()


Better error checks in the describe module

--- library/vending/describe.coffee
+++ library/vending/describe.coffee
@@ -61,9 +61,10 @@
     # process such documentation and do with it whatever is necessary.
     # This approach gives unique ability to build self documented APIs.
     @specification: (method, descriptor) ->
-        validated = _.isFunction descriptor
-        missing = "The #{descriptor} is not a descriptor"
-        throw new Error missing unless validated
+        noMethod = "The #{method} is not a valid method"
+        noDescriptor = "The #{descriptor} is not a descriptor"
+        assert _.isFunction(method), noMethod
+        assert _.isFunction(descriptor), noDescriptor
         method.document ?= new Document
         previous = method.document.descriptor
         method.document.descriptor = ->
@@ -78,12 +79,11 @@
     collectSpecifications: (substitution) ->
         services = @kernel?.router?.registry
         services = substitution if substitution?
-        assert _.isArray(services), "no services"
+        assert _.isArray(services), "invalid services"
         logger.debug "Collecting API documentation"
         _.map services, (service) -> do (service) ->
-            constructor = service.constructor
-            supported = constructor.SUPPORTED
             unsupported = service.unsupported
+            supported = service.constructor.SUPPORTED
             implemented = (m) -> service[m] isnt unsupported
             doc = (m) -> service[m].document or new Document
             filtered = _.filter supported, implemented


change locahost to production domain name

--- app/assets/javascripts/angular/controllers/graphs_ctrl.js.coffee
+++ app/assets/javascripts/angular/controllers/graphs_ctrl.js.coffee
@@ -51,7 +51,7 @@
         max: MAXIMUM
         differenceCount: differenceResponseCount
       }
-    socket = io.connect('//"#{Settings.application_domain}":8080/')
+    socket = io.connect('//wci-chpir.duke.edu:8080/') #TODO Extract
     socket.on "message", (data) ->
       data = JSON.parse(data)
       if data.count != 0


prevented alt+n and alt+p from performing their actions twice

--- client/ide.coffee
+++ client/ide.coffee
@@ -224,8 +224,8 @@
             {'': 'New _Session', key: 'Ctrl+N', action: D.rideNewSession}
             '-'
             {'': '_Load Demo...', action: loadDemo}
-            {'': '_Next Line from Demo',     key: 'Alt+N', action: nextLineFromDemo}
-            {'': '_Previous Line from Demo', key: 'Alt+P', action: prevLineFromDemo}
+            {'': '_Next Line from Demo',     dontBindKey: 1, key: 'Alt+N', action: nextLineFromDemo}
+            {'': '_Previous Line from Demo', dontBindKey: 1, key: 'Alt+P', action: prevLineFromDemo}
           ]
             .concat(
               if D.process?.platform != 'darwin' then [ # Mac's menu already has an item for Quit


Finally suppressLogs in prod.

Finally suppressLogs in prod.

--- config/main.kontrol-prod.coffee
+++ config/main.kontrol-prod.coffee
@@ -115,7 +115,7 @@
       useNeo4j: yes
       logToExternal : yes
       resourceName: socialQueueName
-      suppressLogs: no
+      suppressLogs: yes
       version   : version
       mainUri   : "http://koding.com"
       broker    :