Fixes file

Fixes file

--- src/coffee/util/crossfilterservice.coffee
+++ src/coffee/util/crossfilterservice.coffee
@@ -27,33 +27,34 @@
             sum: 0
             valueOf: ->
                 if @count isnt 0 then @sum / @count else 0
-        @reduceCount = (group) ->
-            group.reduce (p,v) ->
-                p + 1
-            , (p, v) ->
-                p - 1
-            , (p) -> 0
-        @reduceSum = (group, accessor) ->
-            group.reduce (p,v) ->
-                val = accessor v
-                if val? then p + val else p
-            , (p,v) ->
-                val = accessor v
-                if val? then p - val else p
-            , (p) -> 0
-        @avgOthersGrouper = (chart) ->
-            (topRows) ->
-                topRowsCount = d3.sum topRows, (d) -> d.value.count
-                topRowsSum = d3.sum topRows, (d) -> d.value.sum
-                allRows = chart.group().all()
-                allRowsCount = d3.sum allRows, (d) -> d.value.count
-                allRowsSum = d3.sum allRows, (d) -> d.value.sum
-                topKeys = topRows.map chart.keyAccessor()
-                allKeys = allRows.map chart.keyAccessor()
-                topSet = d3.set topKeys
-                others = allKeys.filter (d) -> !topSet.has d
-                if allRows > topRowsSum then topRows.concat
-                    others: others
-                    key: chart.othersLabel()
-                    value: (allRowsSum - topRowsSum) / (allRowsCount - topRowsCount)
-                else topRows
+    @reduceCount = (group) ->
+        group.reduce (p,v) ->
+            p + 1
+        , (p, v) ->
+            p - 1
+        , (p) -> 0
+    @reduceSum = (group, accessor) ->
+        group.reduce (p,v) ->
+            val = accessor v
+            if val? then p + val else p
+        , (p,v) ->
+            val = accessor v
+            if val? then p - val else p
+        , (p) -> 0
+    @avgOthersGrouper = (chart) ->
+        (topRows) ->
+            topRowsCount = d3.sum topRows, (d) -> d.value.count
+            topRowsSum = d3.sum topRows, (d) -> d.value.sum
+            allRows = chart.group().all()
+            allRowsCount = d3.sum allRows, (d) -> d.value.count
+            allRowsSum = d3.sum allRows, (d) -> d.value.sum
+            topKeys = topRows.map chart.keyAccessor()
+            allKeys = allRows.map chart.keyAccessor()
+            topSet = d3.set topKeys
+            others = allKeys.filter (d) -> !topSet.has d
+            if allRows > topRowsSum then topRows.concat
+                others: others
+                key: chart.othersLabel()
+                value: (allRowsSum - topRowsSum) / (allRowsCount - topRowsCount)
+            else topRows
+    null


sample printing of the embed string

sample printing of the embed string

--- subtree/bokehjs/static/coffee/base.coffee
+++ subtree/bokehjs/static/coffee/base.coffee
@@ -599,6 +599,7 @@
   marksize : 3
   initialize : (options) ->
     @plot_model = options.plot_model
+    console.log("script_inject", @plot_model.get('script_inject'))
     @plot_view = options.plot_view
     ctx = @plot_view.ctx
     if (!ctx.setLineDash)


MultiInput: Added an option to select the shown keys manually without using a MultiInputControl. See #55692

--- src/elements/MultiInput/MultiInput.coffee
+++ src/elements/MultiInput/MultiInput.coffee
@@ -38,10 +38,15 @@
 			content_size:
 				default: false
 				check: Boolean
+			user_selectable:
+				default: false
+				check: Boolean

 	readOpts: ->
 		super()
 		@__inputs = null
+		@__userSelectedData = {}
+		@__user_selectable = @_user_selectable

 	disable: ->
 		super()
@@ -93,9 +98,12 @@

 			input.setCheckChangedValue(v)

+			# All keys are selected when user_selectable option is false, otherwise the only ones with values are selected.
+			@__userSelectedData[input.getName()] = not @__user_selectable or (@__user_selectable and not CUI.util.isEmpty(v))
+		return
+
 	setInputVisibility: ->
 		# the "append" re-orders the input, if needed
-
 		names = (key.name for key in @_control.getKeys())
 		# sort input by key
 		@__inputs.sort (a, b) =>
@@ -107,14 +115,14 @@
 		ok = false
 		for inp in @__inputs
 			CUI.dom.append(@__multiInputDiv, inp.DOM)
-			if @_control.isEnabled(inp.getName())
+			if @_control.isEnabled(inp.getName()) and @__userSelectedData[inp.getName()]
 				inp.show()
 				ok = true
 			else
 				inp.hide()

 		if not ok
-			console.warn("MulitInput.setInputVisibility: No input visible.", input: @__inputs, control: @_control)
+			console.warn("MultiInput.setInputVisibility: No input visible.", input: @__inputs, control: @_control)

 		CUI.Events.trigger
 			type: "content-resize"
@@ -151,12 +159,10 @@
 		CUI.Events.listen
 			type: "multi-input-control-update"
 			node: @__multiInputDiv
-			call: (ev) =>
-				# console.debug ev.getType(), @__multiInputDiv[0], @_control.getKeys()
+			call: (_, info) =>
+				if not CUI.util.isUndef(info.user_selectable)
+					@__user_selectable = info.user_selectable
 				@setInputVisibility()
-
-		# DOM.registerEvent(multiInputDiv, "easydbui-multi-input-control-update")
-		# multiInputDiv.on "easydbui-multi-input-control-update", (ev)

 		@__inputs = []

@@ -173,22 +179,54 @@
 				undo_support: false
 				content_size: @_content_size
 				placeholder: @_placeholder?[key.name]
+				onDataInit: (field, data) =>
+					if @__user_selectable and CUI.util.isEmpty(data[field.getName()])
+						field.hide()
+					return

 			input = new CUI.MultiInputInput(input_opts)
 			input.render()

 			do (input, key) =>
-				btn = new CUI.defaults.class.Button
+				button = new CUI.defaults.class.Button
 					text: key.tag
 					tabindex: null
-					disabled: !@_control.hasUserControl()
-					onClick: (ev, btn) =>
-						@_control.showUserControl(ev, btn, @__multiInputDiv)
+					disabled: not @_control.hasUserControl() and not @__user_selectable
 					role: "multi-input-tag"
 					class: "cui-multi-input-tag-button"
 					tooltip: key.tooltip
-
-				input.append(btn, "right")
+					onClick: (ev) =>
+						if @__user_selectable
+							form.reload()
+							userSelectablePopover.show()
+						else
+							@_control.showUserControl(ev, button, @__multiInputDiv)
+
+				form = new CUI.Form
+					data: @__userSelectedData
+					fields: =>
+						fields = @_control.getKeys().map((key) =>
+							type: CUI.Checkbox
+							name: key.name
+							text: key.tooltip.text
+							onDataChanged: (data, field) =>
+								if Object.values(@__userSelectedData).some((val) -> val)
+									return
+								data[field.getName()] = true
+								field.reload()
+						)
+						return fields
+					onDataChanged: =>
+						@setInputVisibility()
+				form.start()
+
+				userSelectablePopover = new CUI.Popover
+					pane:
+						padded: true
+						content: form
+					element: button
+
+				input.append(button, "right")

 				CUI.Events.listen
 					type: "data-changed"
@@ -202,7 +240,6 @@
 			@__inputs.push(input)
 		return

-
 	render: ->
 		super()
 		@__initInputs()


Purge messages so ithe app does not crash due to OOM

--- src/main/assets/javascripts/simple.coffee
+++ src/main/assets/javascripts/simple.coffee
@@ -86,6 +86,8 @@

 downloadResourceData = (map) ->
   handleDownloadCallback = (response) ->
+    $('div.messages').empty()
+
     response.forEach (v) ->
       handleGeoJsonPacket(map, v)
   $.get '/fgis/api/resource', {}, handleDownloadCallback, 'json'


update.

update.

--- src/main/public/nz/SpriteCharacter.coffee
+++ src/main/public/nz/SpriteCharacter.coffee
@@ -18,8 +18,10 @@
   init: (@index,@character) ->
     @superInit(@character.spriteSheet)

-    #canvas = tm.graphics.Canvas().resize(@width, @height).drawTexture(@ss.image,0,0)
-    #@ss.image.element = canvas.element
+    canvas = tm.graphics.Canvas()
+      .resize(@ss.image.width, @ss.image.height)
+      .drawTexture(@ss.image,0,0)
+    @ss.image.element = canvas.element

     @checkHierarchy = true
     @ghost = null


Fixing typo

Fixing typo

--- example/source/second/main.coffee
+++ example/source/second/main.coffee
@@ -3,7 +3,7 @@
   @scaffold "source/second/main.yml"

   buttonClick: ->
-    modal = new Atoms.Organism.Confirm
+    modal = new Atoms.Molecule.Confirm
       icon    : "search"
       title   : "Find your friends"
       text    : "lorem ipsum"


typo fixed and attachment description added

--- app/assets/javascripts/controllers/faq.coffee
+++ app/assets/javascripts/controllers/faq.coffee
@@ -23,7 +23,7 @@

Summary of accounts

A summary of net values is available for your assets and liabilities (Balance Sheet) as well as your incomes and expenses
-			(Profit/Loss). You can select between lists to give a more customized feedback.
+			(Profit/Loss). You can select between lists to give a more customized result.

Security

All communications between your browser and our server are encrypted with TLS. Your data remains private even if you're using public internet.

@@ -61,8 +61,8 @@

Monthly Salary and Bonus for a personal income account

Meal Cost and Accommodation Fee for a \"Beijing trip\" expense account

-
Saving and Cash for a \"Bank\" asset accounts

-
Debt Owed and Repayment Returned for a \"Debt\" liability accounts

+
Saving and Cash for a \"Bank\" asset account

+
Debt Owed and Repayment Returned for a \"Debt\" liability account

 			"
 		},
@@ -75,8 +75,9 @@

To create a transaction, simply typing in a name inside the new transaction bar
 				and a new form will appear for filling in the amount.

Click on existing transactions to see the detail. You could also add or edit the name,
-				description, amount, due date,
-				and assignee, or even make comments about the transaction.

+				description, amount, due date,
+				assignee and attachment,
+				or even make comments about the transaction.

 			"
 		},
 		{


When user signout, refresh the page

When user signout, refresh the page

--- app/assets/javascripts/routes/sessions.coffee
+++ app/assets/javascripts/routes/sessions.coffee
@@ -4,4 +4,4 @@

 Dashboard.SessionsDestroyRoute = Ember.Route.extend
   activate: ->
-    @auth.signOut()
+    @auth.signOut().then -> window.location.reload true


errcodes as comments in const.coffee

errcodes as comments in const.coffee

--- src/iced/const.coffee
+++ src/iced/const.coffee
@@ -33,3 +33,34 @@
 		NORMAL: 10000
 	err_code_list:
 		username_error: "用户名错误"
+###
+    var code = {
+#        "username_error": function() {
+ #           alert("用户名错误");
+  #          $('#uname').focus();
+ #       },
+  #      "password_error": function() {
+   #         alert("密码错误");
+            $('#password').focus();
+        },
+        "user_tab_error": "认证程序未启动",
+        "user_group_error": "您的计费组信息不正确",
+        "non_auth_error": "您无须认证，可直接上网",
+        "status_error": "用户已欠费，请尽快充值。",
+        "available_error": "您的帐号已停用",
+        "delete_error": "您的帐号已删除",
+        "ip_exist_error": "IP已存在，请稍后再试。",
+        "usernum_error": "用户数已达上限",
+        "online_num_error": "该帐号的登录人数已超过限额\n" +
+            "请登录https://usereg.tsinghua.edu.cn断开不用的连接。",
+        "mode_error": "系统已禁止WEB方式登录，请使用客户端",
+        "time_policy_error": "当前时段不允许连接",
+        "flux_error": "您的流量已超支",
+        "minutes_error": "您的时长已超支",
+        "ip_error": "您的 IP 地址不合法",
+        "mac_error": "您的 MAC 地址不合法",
+        "sync_error": "您的资料已修改，正在等待同步，请 2 分钟后再试。",
+        "ip_alloc": "您不是这个地址的合法拥有者，IP 地址已经分配给其它用户。",
+        "ip_invaild": "您是区内地址，无法使用。"
+    }[res];
+###


fix q

fix q

--- app/graphite.coffee
+++ app/graphite.coffee
@@ -48,7 +48,7 @@
     For example, `sumSeries(q('twitter.*.tweetcount'))` will be sent as `sumSeries(twitter.*.tweetcount)`.
     """

-  fn 'q', (targets...) ->
+  fn 'q', (ctx, targets...) ->
     for t in targets
       unless _.isString t
         throw new TypeError "#{t} is not a string"


More u.js tests

More u.js tests

--- tests/tests/u_test.coffee
+++ tests/tests/u_test.coffee
@@ -1,12 +1,11 @@

 define [] , () ->
-  module "u.js DOM manipulation tests"
+  module "u.js unit test"

   test "Core", () ->
     ok u, "Got global u helper"

-  test "QuerySelector Test", () ->
-
+  test "Test query selector", () ->
     elements = u("#test1 .foo")
     ok elements, "Got elements"
     equal 6, elements.size()
@@ -15,4 +14,26 @@
     ok elements, "Got elements"
     equal 1, elements.size()

+  test "Test all()", () ->
+    elements = u("#test1 .foo")
+    for el in elements.all()
+      ok el, "Get element"

+  test "Test get(i)", () ->
+    elements = u("#test1 .foo")
+    el = elements.get(0)
+    ok el
+
+  test "Test children(i)", () ->
+    elements = u("#test1 .foo")
+    el = elements.children(0)
+    ok el
+
+  test "Test first()", () ->
+    ok u("#test1 .foo").first()
+    ok u("#test1").first()
+
+  test "Test last()", () ->
+    ok u("#test1 .foo").last()
+    ok u("#test1").last()
+


Fix unit test when false is not at /bin/false

--- test/unit/coffee/SafeExec.coffee
+++ test/unit/coffee/SafeExec.coffee
@@ -25,7 +25,7 @@
 				done()

 		it "should execute a command with non-zero exit status", (done) ->
-			@safe_exec "/bin/false", @options, (err, stdout, stderr) =>
+			@safe_exec "/usr/bin/env false", @options, (err, stdout, stderr) =>
 				stdout.should.equal ""
 				stderr.should.equal ""
 				err.message.should.equal "exit status 1"


Fixed the context-menu preventer in the level editor.

--- app/views/editor/level/thangs_tab_view.coffee
+++ app/views/editor/level/thangs_tab_view.coffee
@@ -179,6 +179,7 @@
   destroy: ->
     @selectAddThangType null
     @surface.destroy()
+    $(document).bind 'contextmenu', @preventDefaultContextMenu
     super()

   onViewSwitched: (e) ->
@@ -426,6 +427,7 @@
     @$el.find('.thangs-column').show()

   preventDefaultContextMenu: (e) ->
+    return unless $(e.target).closest('#canvas-wrapper').length
     e.preventDefault()

   onSpriteContextMenu: (e) ->


removed merge junk

removed merge junk

--- app/views/play/level/LevelPlaybackView.coffee
+++ app/views/play/level/LevelPlaybackView.coffee
@@ -339,11 +339,8 @@
         @slideCount = 0
         @wasPlaying = @playing
         Backbone.Mediator.publish 'level:set-playing', {playing: false}
-<<<<<<< HEAD
-        Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'playback-scrub-start', volume: .01
-=======
         Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'playback-scrub-start', volume: 0.5
->>>>>>> 8c37fabe7990e8409591fee65c18593bb64aee5c
+

       stop: (event, ui) =>
         return if @shouldIgnore()
@@ -355,11 +352,8 @@
           Backbone.Mediator.publish 'level:set-playing', {playing: false}
           @$el.find('.scrubber-handle').effect('bounce', {times: 2})
         else
-<<<<<<< HEAD
-          Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'playback-scrub-end', volume: .01
-=======
           Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'playback-scrub-end', volume: 0.5
->>>>>>> 8c37fabe7990e8409591fee65c18593bb64aee5c
+
     )

   getScrubRatio: ->


Add temporary hour of code redirects. (#129)


Delete init.coffee

Delete init.coffee

--- init.coffee
+++ init.coffee
@@ -1 +0,0 @@
-# Add any auto-loaded Atom code on init here.


automatically process lightcurves for outliers (ignoring low, transit-like, points)

--- app/lib/canvas-graph.coffee
+++ app/lib/canvas-graph.coffee
@@ -84,7 +84,7 @@
     #   @ctx.textAlign = 'left'
     #   @ctx.fillText( @toDataYCoord((-yClick+@canvas.height)).toFixed(4), 15, yClick+5 ) # don't forget to flip y-axis values

-  processLightcurve: (removeOutliers=false) ->
+  processLightcurve: (removeOutliers=true) ->

     @removeOutliers = removeOutliers

@@ -102,8 +102,8 @@
       @data.x[i] = x - @smallestX

     if removeOutliers
-      @data = @processOutliers(@data_raw, nsigma=3) # NOTE: nsigma < 8 removes tutorial subject transits
-
+      @data = @processOutliers(@data_raw, nsigma=4)
+
     @data.y = @normalize(@data.y)

     # update min/max values


scale marks to the EXACT size

scale marks to the EXACT size

--- app/lib/canvas-graph.coffee
+++ app/lib/canvas-graph.coffee
@@ -430,6 +430,14 @@

     # DEBUG CODE
     @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+    @plotPoints(wMin,wMax)
+
     # @rescaleMarks(wMin,wMax)

     # zoom = setInterval (=>
@@ -452,26 +460,32 @@
     [cMin, cMax] = [@xMin, @xMax]
     [wMin, wMax] = [@smallestX, @largestX]

-    @plotPoints(wMin, wMax)
-
-
-    # # TODO: why doesn't this work?
-    # zoom = setInterval (=>
-    #   @plotPoints(cMin,cMax)
-    #   cMin -= 1.0 unless cMin <= wMin
-    #   cMax += 1.0 unless cMax >= wMax
-    #   if cMin <= wMin and cMax >= wMax  # finished zooming
-    #     clearInterval zoom
-    #     classifier.el.find('#graph').removeClass('is-zooming')
-    #     # console.log '*********** [',wMin,',',wMax,'] *********** (done with animation)'
-    #     @plotPoints(wMin, wMax)
-    #     unless callback is undefined
-    #       callback.apply()
-    #       classifier.el.find("#zoom-button").removeClass("zoomed")
-    #       classifier.el.find("#zoom-button").removeClass("allowZoomOut") # for last zoom level
-    #       classifier.el.find('#ui-slider').attr('disabled',true)
-    #       classifier.el.find('.noUi-handle').fadeOut(150)
-    # ), 30
+    # @plotPoints(wMin, wMax)
+    # @plotPoints(wMin, wMax)
+    # @plotPoints(wMin, wMax)
+    # @plotPoints(wMin, wMax)
+    # @plotPoints(wMin, wMax)
+    # @plotPoints(wMin, wMax)
+    # @plotPoints(wMin, wMax)
+
+
+    # TODO: why doesn't this work?
+    zoom = setInterval (=>
+      @plotPoints(cMin,cMax)
+      cMin -= 1.0 unless cMin <= wMin
+      cMax += 1.0 unless cMax >= wMax
+      if cMin <= wMin and cMax >= wMax  # finished zooming
+        clearInterval zoom
+        classifier.el.find('#graph').removeClass('is-zooming')
+        # console.log '*********** [',wMin,',',wMax,'] *********** (done with animation)'
+        @plotPoints(wMin, wMax)
+        unless callback is undefined
+          callback.apply()
+          classifier.el.find("#zoom-button").removeClass("zoomed")
+          classifier.el.find("#zoom-button").removeClass("allowZoomOut") # for last zoom level
+          classifier.el.find('#ui-slider').attr('disabled',true)
+          classifier.el.find('.noUi-handle').fadeOut(150)
+    ), 30

     return

@@ -595,23 +609,18 @@

-  minWidth: ->
-    console.log 'CANVAS GRAPH XMIN: ', @canvasGraph.xMin
-    console.log 'CANVAS GRAPH XMAX: ', @canvasGraph.xMax
-
-
-    minWidth =  13.03 *  @canvasGraph.scale #((0.5) / ( @canvasGraph.xMax - @canvasGraph.xMin)) * (@canvas.width-@canvasGraph.leftPadding)
-    console.log '//////////////////////////'
-    console.log 'minWidth(): ', minWidth, ' (pixels)'
-    console.log 'minWidth(): ', @canvasGraph.toDays(minWidth), ' (days)'
-    return minWidth
-
-  maxWidth: ->
-    maxWidth = 78.16 * @canvasGraph.scale #parseFloat( @canvasGraph.toPixels(1.0) )   # * (@canvasGraph.scale || 1)
-    console.log '//////////////////////////'
-    console.log 'maxWidth(): ', maxWidth, '(pixels)'
-    console.log 'maxWidth(): ', @canvasGraph.toDays(maxWidth), ' (days)'
-    return maxWidth
+  minWidth: -> 0.5*(@canvas.width-@canvasGraph.leftPadding)/(@canvasGraph.xMax-@canvasGraph.xMin)
+    # DEBUG CODE
+    # minWidth =  0.5*(@canvas.width-@canvasGraph.leftPadding)/(@canvasGraph.xMax-@canvasGraph.xMin)
+    # console.log 'canvasGraph.xMax = ', @canvasGraph.xMax
+    # console.log 'minWidth() = ', minWidth
+    # return minWidth
+
+  maxWidth: -> 2.0*(@canvas.width-@canvasGraph.leftPadding)/(@canvasGraph.xMax-@canvasGraph.xMin)
+    # DEBUG CODE
+    # maxWidth =  2.0*(@canvas.width-@canvasGraph.leftPadding)/(@canvasGraph.xMax-@canvasGraph.xMin)
+    # console.log 'maxWidth() = ', maxWidth
+    # return maxWidth

   handleWidth: -> 16 * (@canvasGraph.scale || 1)


travis-test: simulte if no external config for factory b is availible

--- _src/test/test.coffee
+++ _src/test/test.coffee
@@ -14,6 +14,7 @@
 		appid: "wmshop"
 		config:
 			endpoint: "http://localhost:3000/email/send"
+			simulate: true

 _Cnf =
 	realReceiver: "mp@tcs.de"


Fixed Logger tests

Fixed Logger tests

--- tests/helpers/test_logger.coffee
+++ tests/helpers/test_logger.coffee
@@ -1,7 +1,7 @@

 expect = require('chai').expect

-Logger = require '../../src/helpers/logger'
+Logger = require('../../src/helpers/logger')()

 describe 'Logger', ->
   describe '#log', ->


Make callback optional for HTTP.TentClient.find()

--- assets/javascripts/http/tent_client.js.coffee
+++ assets/javascripts/http/tent_client.js.coffee
@@ -44,7 +44,7 @@
     return unless (entity = params.entity)

     if client = @entity_mapping[entity]
-      callback(client)
+      callback?(client)
       return client

     unless (options.hasOwnProperty('fetch') && !options.fetch)
@@ -61,7 +61,7 @@
     if TentStatus.Helpers.isCurrentEntity(entity)
       client = @currentEntityClient(options)
       @entity_mapping[entity] = client
-      return callback(client)
+      return callback?(client)

     # Following proxy broken atm
     options.skip_following_check = true
@@ -71,7 +71,7 @@
         if xhr.status == 200
           client = @currentEntityFollowingProxyClient(res.id, options)
           @entity_mapping[entity] = client
-          callback(client)
+          callback?(client)
         else
           @fetch(params, callback, _.extend(options, {skip_following_check: true}))

@@ -81,7 +81,7 @@
         middleware: [].concat(@middleware.tent)
       }, options.client_options)
       @entity_mapping[entity] = client
-      return callback(client)
+      return callback?(client)

     if (cid = TentStatus.Models.Profile.entity_mapping[entity]) && (profile = TentStatus.Models.Profile.find(cid: cid, fetch: false))
       if profile.get('servers').length
@@ -90,7 +90,7 @@
           middleware: [].concat(@middleware.tent)
         }, options.client_options)
         @entity_mapping[entity] = client
-        return callback(client)
+        return callback?(client)

     client = new HTTP.Client _.extend({
       hosts: [TentStatus.config.tent_proxy_root + "/#{encodeURIComponent entity}"]
@@ -98,5 +98,5 @@
     }, options.client_options)

     @entity_mapping[entity] = client
-    callback(client)
+    callback?(client)


DefineStackView: handleCheckTemplate will run the template over kloud's plan then updates the template based on the response

--- client/admin/lib/views/stacksv2/definestackview.coffee
+++ client/admin/lib/views/stacksv2/definestackview.coffee
@@ -126,6 +126,40 @@
             failed err
             console.warn '[KLOUD:Bootstrap:Fail]', err

+
+  handleCheckTemplate: (options, callback) ->
+
+    { stackTemplate } = options
+    { computeController } = kd.singletons
+
+    computeController.getKloud()
+      .checkTemplate { stackTemplateId: stackTemplate._id }
+      .nodeify (err, response) =>
+
+        console.log '[KLOUD:checkTemplate]', err, response
+
+        if err or not response
+          @outputView
+            .add 'Something went wrong with the template:'
+            .add err?.message or 'No response from Kloud'
+
+          callback err
+
+        else
+
+          machines = parseTerraformOutput response
+
+          @outputView
+            .add 'Template check complete succesfully'
+            .add 'Following machines will be created:'
+            .add JSON.stringify machines, null, 2
+            .add 'This stack has been saved succesfully!'
+
+          updateStackTemplate {
+            stackTemplate, machines
+          }, callback
+
+
   saveTemplate: (callback) ->

     {stackTemplate} = @getData()


Fix issue with has-error class not applying while focused

--- client/controllers/incidentReports/incidentForm.coffee
+++ client/controllers/incidentReports/incidentForm.coffee
@@ -115,5 +115,11 @@
       firstItem.remove()

   'submit form': (event, instance) ->
-    instance.data.valid.set(not event.isDefaultPrevented())
+    prevented = event.isDefaultPrevented()
+    instance.data.valid.set(not prevented)
+    if prevented
+      # Toggle focus on location input so 'has-error' class is applied
+      if not instance.$('.select2-selection__choice').length
+        instance.$('.select2-search__field').blur()
+        instance.$('.has-error:first-child').focus()
     event.preventDefault()


rollbar: log kite timeouts

rollbar: log kite timeouts

--- client/landing/app/MainApp/kodingappscontroller.coffee
+++ client/landing/app/MainApp/kodingappscontroller.coffee
@@ -103,7 +103,9 @@
           @putAppsToAppStorage manifests
           callback? null, manifests
     , ->
-      log "Timeout reached for kite request"
+      msg = "Timeout reached for kite request"
+      KD.logToExternal msg
+      log msg
       callback()

   fetchAppsFromDb:(callback)->


Removed nonsensical comment

Removed nonsensical comment

--- core/app/backbone/contrib/default_click_handler.coffee
+++ core/app/backbone/contrib/default_click_handler.coffee
@@ -4,8 +4,6 @@
 Backbone.View::defaultClickHandler = (e, routeTo=null) ->
   routeTo ||= $(e.target).closest("a").attr("href")

-  # Return if a modifier key is pressed or when Backbone has not properly been initialized
-  # Make sure we return "true" so other functions can determine what happened
   if e.metaKey or e.ctrlKey or e.altKey
     window.open routeTo, "_blank"
   else if not Backbone.History.started # Capitalization in Backbone.[H]istory is intentional


Client: Activity: Added handleUnsetMessageEditMode test method to messagestore

--- client/activity/lib/flux/test/messagesstore.coffee
+++ client/activity/lib/flux/test/messagesstore.coffee
@@ -251,3 +251,21 @@
       message = storeState.get messageId
       expect(message.get '__isEditing').to.equal yes

+
+  describe '#handleUnsetMessageEditMode', ->
+
+    message         = null
+    messageId       = 'unsetEditMode'
+    clientRequestId = 'testclient'
+    message         = MessageCollectionHelpers.createFakeMessage messageId, 'hello world'
+
+    it 'sets message __isEditing value to no', ->
+
+      reactor.dispatch actionTypes.CREATE_MESSAGE_SUCCESS, { clientRequestId, message }
+      reactor.dispatch actionTypes.UNSET_MESSAGE_EDIT_MODE, { messageId }
+
+      storeState = reactor.evaluate ['messages']
+
+      message = storeState.get messageId
+      expect(message.get '__isEditing').to.equal no
+


app: don't use map as children

app: don't use map as children

--- client/app/lib/components/sidebarlist/index.coffee
+++ client/app/lib/components/sidebarlist/index.coffee
@@ -19,7 +19,7 @@
     if componentProp is 'SidebarMessagesListItem'
       threads = threads.slice 0, previewCount

-    threads.map (thread) ->
+    threads.toList().map (thread) ->
       id = thread.getIn ['channel', 'id']
       <Component key={id} active={id is selectedId} thread={thread} />


finished paper model test.

finished paper model test.

--- test/javascripts/models/paper_test.coffee
+++ test/javascripts/models/paper_test.coffee
@@ -43,7 +43,7 @@
     paper.setProperties phase: phase
     paper.get 'allTasks'

-  equal allTasks, [task1, task2]
+  deepEqual allTasks.mapBy('title'), [task1.get('title'), task2.get('title')]

 test 'Paper hasMany assignees as User', ->
   relationships = Ember.get ETahi.Paper, 'relationships'


Move trace from app "start" to app "before:start"

--- app/example/index.coffee
+++ app/example/index.coffee
@@ -13,11 +13,10 @@
     require('./routes')
     Visualizer = require('ui-router-visualizer').Visualizer
     @router.plugin(Visualizer)
+    @router.trace.enable()
+    @router.trace.enable("TRANSITION", "UIVIEW", "VIEWCONFIG")

   App.on "start", ->
     @router.start(App.rootRegion)

-    @router.trace.enable()
-    @router.trace.enable("TRANSITION", "UIVIEW", "VIEWCONFIG")
-
   return App


Reenabled redrawing every frame

Reenabled redrawing every frame

--- src/js/Game.coffee
+++ src/js/Game.coffee
@@ -25,7 +25,7 @@
   Game::start = ->
     frame = =>
       @world.update()
-      if Math.random() < 0.1 then @world.draw()
+      @world.draw()
       @requestId = window.requestAnimationFrame frame

     frame()


Get "Type your text here" to show when text left empty, for #507

--- src/resources/forms/orbeon/builder/resources/cell/control-resources-editor/actions.coffee
+++ src/resources/forms/orbeon/builder/resources/cell/control-resources-editor/actions.coffee
@@ -96,8 +96,9 @@
     setValue          : (newValue) ->
                             if lhha() == 'text'
                                 afterTinyMCEInitialized ->
-                                    tinymceObject.setContent(newValue)
-
+                                    # Workaround to TinyMCE issue, see https://twitter.com/avernet/status/578986913694109696
+                                    valueSet = if newValue == '' then '<span>' else newValue
+                                    tinymceObject.setContent(valueSet)
                             else
                                 textfield.val(newValue)
                                 textfield.focus()


add tests with coverage

add tests with coverage

--- Gulpfile.coffee
+++ Gulpfile.coffee
@@ -1,6 +1,8 @@
 gulp       = require 'gulp'
 gutil      = require 'gulp-util'
 mocha      = require 'gulp-mocha'
+coveralls  = require 'gulp-coveralls'
+run        = require 'gulp-run'
 coffee     = require 'gulp-coffee'
 browserify = require 'browserify'
 coffeeify  = require 'coffeeify'
@@ -17,11 +19,11 @@
 NAME = 'gerberToSvg'

 # source code and destination code locations
-SRCDIR = './src/*.coffee'
+SRC = './src/*.coffee'
 LIBDIR = './lib'

 gulp.task 'default', [ 'standalone' ], ->
-  gulp.src SRCDIR
+  gulp.src SRC
     .pipe coffee()
       .on 'error', gutil.log
     .pipe gulp.dest LIBDIR
@@ -56,11 +58,29 @@
     .pipe mocha {
       reporter: 'spec'
       globals: {
-        should: require('should')
-        coffee: require('coffee-script/register')
+        should: require 'should'
+        coffee: require 'coffee-script/register'
         stack: Error.stackTraceLimit = 3
       }
     }
+
+# this is ugly but it works...
+gulp.task 'coverage2', ->
+  run 'mocha --compilers coffee:coffee-script/register
+    -r blanket -r should
+    -R html-cov', { silent: true }
+    .exec()
+    .pipe rename 'coverage.html'
+    .pipe gulp.dest '/Users/mc/Desktop'
+
+# this is also ugly and might work...
+gulp.task 'coverage', ->
+  run 'mocha --compilers coffee:coffee-script/register
+    -r blanket -r should
+    -R mocha-lcov-reporter', { silent: true }
+    .exec()
+    .pipe rename 'lcov.info'
+    .pipe coveralls()

 gulp.task 'testwatch', ['test', 'default'], ->
   gulp.watch ['./src/*', './test/*'], ['test', 'default']


payments: update includes to reflect refactoring

--- client/includes.coffee
+++ client/includes.coffee
@@ -150,8 +150,11 @@
   "app/MainApp/payment/paymentcontroller.coffee",
   "app/MainApp/payment/billingmethodchoice.coffee",
   "app/MainApp/payment/billingform.coffee",
+  "app/MainApp/payment/billingformmodal.coffee",
   "app/MainApp/payment/paymentconfirmationmodal.coffee",
   "app/MainApp/payment/paymentdeleteconfirmationmodal.coffee",
+  "app/MainApp/payment/buyvmconfirmview.coffee"
+  "app/MainApp/payment/buyvmmodal.coffee",

   #maintabs


Tests: Environments: VM: Change test name.

--- tests/src/environments/vm.coffee
+++ tests/src/environments/vm.coffee
@@ -34,6 +34,7 @@

   CheckVMDiskUsage: (browser) ->
+  checkVMDiskUsage: (browser) ->

     diskUsageSelector     = modalSelector + ' .diskusage'
     diskUsageBarSelector  = diskUsageSelector + ' .input-wrapper .progressbar-container.disk-usage'


Tests: Change timers.

Tests: Change timers.

--- tests/src/helpers/helpers.coffee
+++ tests/src/helpers/helpers.coffee
@@ -22,9 +22,9 @@
   doLogin: (browser, user) ->

     browser
-      .waitForElementVisible  '[testpath=main-header]', 5000
+      .waitForElementVisible  '[testpath=main-header]', 50000
       .click                  '#main-header [testpath=login-link]'
-      .waitForElementVisible  '[testpath=login-container]', 5000
+      .waitForElementVisible  '[testpath=login-container]', 50000
       .setValue               '[testpath=login-form-username]', user.username
       .setValue               '[testpath=login-form-password]', user.password
       .click                  '[testpath=login-button]'
@@ -140,9 +140,9 @@
     webSelector   = "span[title='" + webPath + "']"

     browser
-      .waitForElementVisible   '.vm-header', 5000
+      .waitForElementVisible   '.vm-header', 50000
       .click                   '.vm-header .buttons'
-      .waitForElementPresent   '.context-list-wrapper', 5000
+      .waitForElementPresent   '.context-list-wrapper', 50000
       .click                   '.context-list-wrapper .refresh'
       .waitForElementVisible   webSelector, 10000
       .click                   webSelector
@@ -158,11 +158,12 @@
     filename  = paragraph.split(' ')[0] + '.txt'

     browser
-      .waitForElementVisible    'li.new-file', 5000
+      .waitForElementVisible    'li.new-file', 50000
       .click                    'li.new-file'
       .waitForElementVisible    'li.selected .rename-container .hitenterview', 5000
       .clearValue               'li.selected .rename-container .hitenterview'
       .setValue                 'li.selected .rename-container .hitenterview', filename + '\n'
+      .pause                    2000 # required
       .waitForElementPresent    "span[title='" + webPath + '/' + filename + "']", 5000 # Assertion

     return filename


fix tree errors

fix tree errors

--- app/components.coffee
+++ app/components.coffee
@@ -59,7 +59,7 @@
         @props.create_node _.extend {}, @props, {node: child}
       child = React.DOM.ul null, _.sortBy child_nodes, (node) -> node.props.name
     else if state == 'failed'
-      child = @props.create_error_node props
+      child = @props.create_error_node(@props)
     else
       child = null
     if @props.node.is_leaf


social: minor fixes in aggregate selector

--- workers/social/lib/social/models/activeitems.coffee
+++ workers/social/lib/social/models/activeitems.coffee
@@ -35,8 +35,8 @@
     matcher     = {
       sourceName : klass.name
       as         : $in : as
-      $lte       : endOfToday   = new Date Date.now()
-      $gte       : startOfToday = new Date Date.now() - 1000*60*60*24 # 24 hours
+      $lte       : new Date Date.now()
+      $gt        : new Date Date.now() - 1000*60*60*24 # 24 hours
     }

     Relationship.getCollection().aggregate {$match: matcher},


models/group: default team member count to 1

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -272,7 +272,9 @@
         ]]
       # parent        : ObjectRef
       counts        :
-        members     : Number
+        members     :
+          type      : Number
+          default   : -> 1
       customize     :
         coverPhoto  : String
         logo        : String


Social: send notification on role change

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -658,7 +658,8 @@
             JAccount.one { _id: targetId }, (err, account) ->
               return callback err  if err

-              account.sendNotification 'MembershipRoleChanged', { role, group: client.context.group }  if account
+              contents = { role, group: client.context.group, adminNick: client.connection.delegate.profile.nickname }
+              account.sendNotification 'MembershipRoleChanged', contents  if account
               queue.next()

         # remove existing ones


Groups: removed obsolete vocabulary removal.

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -1263,10 +1263,6 @@
           JInvitation = require '../invitation'
           removeHelperMany JInvitation, requests, err, callback, queue

-        => @fetchVocabularies (err, vocabularies)->
-          JVocabulary = require '../vocabulary'
-          removeHelperMany JVocabulary, vocabularies, err, callback, queue
-
         => @fetchTags (err, tags)->
           JTag = require '../tag'
           removeHelperMany JTag, tags, err, callback, queue


groups: decorate `JPaymentPlan` model into `JPaymentSubscription`

--- workers/social/lib/social/models/group/index.coffee
+++ workers/social/lib/social/models/group/index.coffee
@@ -1473,6 +1473,16 @@
       JPaymentSubscription.one _id: id, (err, subscription) =>
         @addSubscription subscription, callback

+  fetchSubscription$: secure (client, callback) ->
+    @fetchSubscription (err, subscription) ->
+      return callback err  if err
+      {planCode} = subscription
+      JPaymentPlan = require '../payment/plan'
+      JPaymentPlan.one {planCode}, (err, plan) ->
+        return callback err  if err
+        subscription.plan = plan
+        callback null, subscription
+
   createGroupBotAndPostMessage: (client, callback) ->
     # get groupbot account
     JAccount = require '../account'


Using form submit events.

Using form submit events.

--- client/settings.coffee
+++ client/settings.coffee
@@ -26,7 +26,7 @@

 # Username settings
 Template.settingsUsername.events =
-  'click button.set-username': (event, template) ->
+  'submit form#set-username': (event, template) ->
     event.stopPropagation()
     event.preventDefault()
     usernameReadyForValidation = true
@@ -84,7 +84,7 @@

 # Password settings
 Template.settingsPassword.events =
-  'click button.change-password': (event, template) ->
+  'submit form#set-password': (event, template) ->
     newPasswordReadyForValidation = true
     passwordFormMessages.resetMessages()
     event.preventDefault()


Referral: add campaign to the scriptblock

--- workers/social/lib/social/render/scriptblock.coffee
+++ workers/social/lib/social/render/scriptblock.coffee
@@ -11,11 +11,13 @@
   {argv} = require 'optimist'

   prefetchedFeeds = {}
-  {client, intro, landing} = options
+  campaignData = {}
+  {bongoModels, client, intro, landing} = options

   createHTML = ->
     replacer    = (k, v)-> if 'string' is typeof v then encoder.XSSEncode v else v
     encodedFeed = JSON.stringify prefetchedFeeds, replacer
+    encodedCampaignData = JSON.stringify campaignData, replacer

     landingOptions =
       page         : landing
@@ -40,6 +42,7 @@
     <script src='/a/js/koding.#{KONFIG.version}.js'></script>
     #{if landing then "<script src='/a/js/landingapp.#{ KONFIG.version }.js'></script>" else ''}
     <script>KD.prefetchedFeeds=#{encodedFeed};</script>
+    <script>KD.campaign=#{encodedCampaignData};</script>

     <!-- GOOGLE ANALYTICS -->
@@ -80,8 +83,13 @@
     """

   generateScript = ->
-    html = createHTML()
-    return callback null, html
+    bongoModels.JReferral.isCampaingValid (err, status, campaign)->
+      if not err
+        content = campaign?.content
+        campaignData = {status, content}
+
+      html = createHTML()
+      return callback null, html

   {delegate} = options.client.connection
   # if user is exempt or super-admin do not cache his/her result set


added setdevice command

added setdevice command

--- main.coffee
+++ main.coffee
@@ -289,6 +289,16 @@
       .map (line, i) -> "#{i}\t#{line.replace /\[.+\]/, ''}"
       .join '\n')

+cli.command 'setdevice <index>'
+  .description 'Choose simulator device by index'
+  .action (index) ->
+    unless device = getDeviceList()[parseInt index, 10]
+      logErr 'Invalid device index. Run natal listdevices for valid indexes.'
+
+    config = readConfig()
+    config.device = pluckUuid device
+    writeConfig config
+

 unless semver.satisfies process.version[1...], nodeVersion
   logErr """


Newline error in mimetype

Newline error in mimetype

--- main.coffee
+++ main.coffee
@@ -169,7 +169,7 @@
   file = "#{__dirname}/uploads/#{req.params.fileid}"
   if /^[a-f0-9A-F]+$/.test(req.params.fileid) and fs.existsSync(file)
     db.mimetypeForFile req.params.fileid, (mimetype) ->
-      res.set 'Content-Type', mimetype
+      res.set 'Content-Type', mimetype.trim()
       res.sendfile file
   else res.send 404


Show nearby users in `/node-game/`. References #296.

--- main.coffee
+++ main.coffee
@@ -188,26 +188,28 @@
 app.get '/game/', phpgate # PHP

-app.get '/node-game/', (request, response) ->
+app.get '/node-game/', (request, response) -> sync ->
 	if request.uonline.basicOpts.loggedIn is true
 		options = request.uonline.basicOpts
 		options.instance = 'game'
 		tmpArea = utils.game.getUserArea.sync null, mysqlConnection, request.uonline.basicOpts.userid
-		utils.game.getUserLocation mysqlConnection, request.uonline.basicOpts.userid, (error, result) ->
-			if error? then throw new Error(error)
-			options.location_name = result.title
-			options.area_name = tmpArea.title
-			options.pic = options.picture  if options.picture?
-			options.description = result.description
-			options.ways = result.goto
-			options.ways.forEach (i) -> # facepalm
-				i.name = i.text
-				i.to = i.id
-			options.players_list = [] # TODO: broken
-			options.monsters_list = [] # TODO: broken
-			options.fight_mode = false # TODO: broken
-			options.autoinvolved_fm = false # TODO: broken
-			response.render 'game', options
+		result = utils.game.getUserLocation.sync null, mysqlConnection, request.uonline.basicOpts.userid
+		options.location_name = result.title
+		options.area_name = tmpArea.title
+		options.pic = options.picture  if options.picture?
+		options.description = result.description
+		options.ways = result.goto
+		options.ways.forEach (i) -> # Facepalm. #273
+			i.name = i.text
+			i.to = i.id
+		tmpUsers = utils.game.getUsersOnLocation.sync null, mysqlConnection, result.id
+		tmpUsers.forEach (i) -> # Facepalm. Refs #273 too.
+			i.name = i.user
+		options.players_list = tmpUsers
+		options.monsters_list = [] # TODO: broken
+		options.fight_mode = false # TODO: broken
+		options.autoinvolved_fm = false # TODO: broken
+		response.render 'game', options
 	else
 		response.redirect '/login/'


Update for online server

Update for online server

--- main.coffee
+++ main.coffee
@@ -29,16 +29,10 @@
 app.use passport.initialize()
 app.use passport.session()

-if process.env.NODE_ENV isnt 'production'
-	options =
-		returnURL: 'http://localhost:3000/auth/supinfo/return'
-		realm: 'http://localhost:3000/'
-		identifierField: 'username'
-else
-	options =
-		returnURL: 'http://arkanoid.herokuapp.com/auth/supinfo/return'
-		realm: 'http://arkanoid.herokuapp.com/'
-		identifierField: 'username'
+options =
+	returnURL: 'http://arkanovoid.leops.me/auth/supinfo/return'
+	realm: 'http://arkanovoid.leops.me/'
+	identifierField: 'username'

 passport.use new SupinfoStrategy(options,
 	(identifier, profile, done) ->


Halve the move ratio for collison response

--- app/js/contact.coffee
+++ app/js/contact.coffee
@@ -87,7 +87,7 @@
     return if totalInertia <= 0 # nobody's goin' nowhere

     # how far per inertia should each body move?
-    moveRatio = @depth / totalInertia
+    moveRatio = @depth / totalInertia / 2

     [linearMove, angularMove] = @calculateMove @from, moveRatio, @offset
     linearChange   = @from.changePosition @normal, linearMove


#958 - Group IDs and labels are repeated

--- jsapp/xlform_model_view/model.configs.coffee
+++ jsapp/xlform_model_view/model.configs.coffee
@@ -218,11 +218,9 @@
     name:
       value: ""
     label:
+      last_group_number: 1
       value: (s)->
-        n = 1
-        count_grps = (r)-> n++  if r.constructor.kls is "Group"
-        s.getSurvey().forEachRow count_grps, includeGroups: true
-        "Group #{n}"
+        "Group #{@last_group_number++}"
     type:
       value: "group"
     _isRepeat:


Set letter-spacing to zero in order_stash_plugin

--- src/plugins/order_stash.coffee
+++ src/plugins/order_stash.coffee
@@ -52,6 +52,7 @@
     width: 250px;
     height: 220px;
     text-align: center;
+    letter-spacing: 0;
     font-family: Verdana, Arial, sans-serif !important;
     box-shadow: 0px 1px 11px 0px rgba(77,77,77,0.33);


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -18,7 +18,7 @@
         width
       } = meterData

-      if
+      if not
       ratio = I[name] / I["max#{name.capitalize()}"]

       if showName || text


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -27,7 +27,7 @@

 someOtherObject.meter 'turbo'
 # => Sets up a turbo meter that will be drawn during the someOtherObject overlay event.
-# Since neither turbo maxTurbo were provided, it is set to the value of I.health (500)
+# Since neither turbo maxTurbo were provided, they are both

 # now player has all the methods provided by this module


Make them intuitive

Make them intuitive

--- client/app/Applications/Environments.kdapplication/views/domains/domaincreationform.coffee
+++ client/app/Applications/Environments.kdapplication/views/domains/domaincreationform.coffee
@@ -3,18 +3,16 @@
   subDomainPattern = \
     /^([a-z0-9]([_\-](?![_\-])|[a-z0-9]){0,60}[a-z0-9]|[a-z0-9])$/

-  # -- Form -- #
   domainOptions = [
     { title : "Create A Subdomain",     value : "subdomain" }
     { title : "Register New Domain",    value : "new"}
     { title : "Use An Existing Domain", value : "existing", disabled : yes }
   ]

-  constructor:(options = {})->
+  constructor:(options = {}, data)->
     options.cssClass = "environments-add-domain-form"
-    super options
+    super options, data

-    # -- Header -- #
     @addSubView @header = new KDHeaderView
       title             : "Add a domain"

@@ -43,14 +41,14 @@
     @newDomainPane = new KDTabPaneView { name : "NewDomain" }
     @newDomainPane.addSubView @newDomainEntryForm = new DomainBuyForm
     @tabs.addPane @newDomainPane
-    @newDomainEntryForm.on 'registerDomain', @bound 'registerNewDomain'
+    @newDomainEntryForm.on 'registerDomain', @bound 'checkDomainAvailability'

     @subDomainPane = new KDTabPaneView { name : "SubDomain" }
     @subDomainPane.addSubView @subDomainEntryForm = new SubDomainCreateForm
     @subDomainEntryForm.on 'registerDomain', @bound 'createSubDomain'
     @tabs.addPane @subDomainPane

-  registerNewDomain: ->
+  checkDomainAvailability: ->
     {createButton}        = @newDomainEntryForm.buttons
     {domains, domainName} = @newDomainEntryForm.inputs
     domainName            = "#{domainName.getValue()}.#{domains.getValue()}"
@@ -65,7 +63,7 @@
     {createButton}        = @subDomainEntryForm.buttons
     domainName            = domainName.getValue()

-    # Test given subdomain
+    # Check given subdomain
     unless subDomainPattern.test domainName
       createButton.hideLoader()
       return notifyUser "#{domainName} is an invalid subdomain."
@@ -168,7 +166,7 @@
       buttons               :
         createButton        :
           name              : "createButton"
-          title             : options.buttonTitle or "Check availability..."
+          title             : options.buttonTitle or "Check availability"
           style             : "cupid-green"
           cssClass          : "add-domain"
           type              : "submit"


Update es-419.coffee

Update es-419.coffee

--- app/locale/es-419.coffee
+++ app/locale/es-419.coffee
@@ -159,9 +159,9 @@
     accepted: "Aceptado"
     rejected: "Rechazado"
     withdrawn: "Retirado"
-#    accept: "Accept"
-#    reject: "Reject"
-#    withdraw: "Withdraw"
+    accept: "Aceptar"
+    reject: "Rechazar"
+    withdraw: "Retirar"
     submitter: "Emisor"
     submitted: "Enviado"
     commit_msg: "Enviar mensaje"
@@ -217,8 +217,8 @@

   play_level:
     done: "Listo"
-#    next_game: "Next game"
-#    show_menu: "Show game menu"
+    next_game: "Siguiente juego"
+    show_menu: "Mostrar menú de juego"
     home: "Inicio" # Not used any more, will be removed soon.
     level: "Nivel" # Like "Level: Dungeons of Kithgard"
     skip: "Omitir"
@@ -343,7 +343,7 @@
     tip_free_your_mind: "Tienes que dejar ir todo, Neo. Miedo, duda, e incredulidad. Libera tu mente. - Morpheus"
     tip_strong_opponents: "Hasta los oponentes mas fuertes siempre tienen una debilidad. - Itachi Uchiha"
     tip_paper_and_pen: "Antes de comenzar a codificar, siempre puedes planear con una hoja de papel y un lapicero."
-#    solve_then_write: "First, solve the problem. Then, write the code. - John Johnson"
+    solve_then_write: "Primero, resuelve el problema. Y entonces, escribe el código. - John Johnson"

   game_menu:
     inventory_tab: "Inventario"
@@ -1120,7 +1120,7 @@
     simulate_games: "¡Simular Juegos!"
     games_simulated_by: "Juegos simulados por ti:"
     games_simulated_for: "Juegos simulados para ti:"
-#    games_in_queue: "Games currently in the queue:"
+    games_in_queue: "Juegos actualmente en cola:"
     games_simulated: "Juegos simulados"
     games_played: "Juegos jugados"
     ratio: "Proporción"
@@ -1157,7 +1157,7 @@
     fight: "Pelea!"
     watch_victory: "Observa tu Victoria"
     defeat_the: "Derrota a"
-#    watch_battle: "Watch the battle"
+    watch_battle: "Mirar la batalla"
     tournament_started: ", iniciado"
     tournament_ends: "Final de Torneo"
     tournament_ended: "Finalizó el Torneo"
@@ -1215,7 +1215,7 @@
     no_recent_games: "No juegos jugados duramente las últimas dos semanas."
     payments: "Pagos"
     prepaid: "Prepagado"
-#    prepaid_codes: "Prepaid Codes"
+    prepaid_codes: "Códigos Prepagados"
     purchased: "Comprado"
     sale: "Venta"
     subscription: "Suscripción"
@@ -1337,7 +1337,7 @@
     input_handling: "Manejo de Entradas"
     math_operations: "Operaciones Matemáticas"
     object_literals: "Objetos Literales"
-#    parameters: "Parameters"
+    parameters: "Parámetros"
     strings: "Cadenas"
     variables: "Variables"
     vectors: "Vectores"


fix(inbox-zero): don't show inbox zero when syncing

--- internal_packages/thread-list/lib/empty-state.cjsx
+++ internal_packages/thread-list/lib/empty-state.cjsx
@@ -117,10 +117,10 @@
     messageOverride = "Nothing to display."
     if @state.layoutMode is 'list'
       ContentComponent = ContentQuotes
+
     if @state.syncing
       messageOverride = "Please wait while we prepare your mailbox."
-
-    if FocusedPerspectiveStore.current()?.name is "Inbox"
+    else if FocusedPerspectiveStore.current()?.name is "Inbox"
       ContentComponent = InboxZero

     classes = classNames


Fix existing add subgroup link

Fix existing add subgroup link

--- lineman/app/components/group_page/subgroups_card/subgroups_card.coffee
+++ lineman/app/components/group_page/subgroups_card/subgroups_card.coffee
@@ -13,4 +13,4 @@
       AbilityService.canAdministerGroup($scope.group) and $scope.group.subgroups().length == 0

     $scope.startSubgroup = ->
-       ModalService.open StartGroupForm, group: -> Records.groups.build(parent_id: $scope.group.id)+       ModalService.open StartGroupForm, group: -> Records.groups.build(parentId: $scope.group.id)


pass display feedback props through to question

--- src/components/exercise/preview.cjsx
+++ src/components/exercise/preview.cjsx
@@ -90,7 +90,7 @@
       <Question
         model={question}
         choicesEnabled={false}
-        show_all_feedback={true}
+        show_all_feedback={@props.displayFeedback}
         type='teacher-review'
         details={details}/>
     )


added priority field to ticket description

If JIRA issue has a priority it will be displayed with other issue fields, since it's one of the most useful properties

--- src/scripts/jira-issues.coffee
+++ src/scripts/jira-issues.coffee
@@ -79,6 +79,9 @@
                     message += ', fixVersion: '+json.fields.fixVersions[0].name
                   else
                     message += ', fixVersion: NONE'
+
+                  if json.fields.priority and json.fields.priority.name
+                    message += ', priority: ' + json.fields.priority.name

                   urlRegex = new RegExp(jiraUrl + "[^\\s]*" + key)
                   if not msg.message.text.match(urlRegex)


Disable auto-saves until the data has been loaded

--- src/scripts/redis-brain.coffee
+++ src/scripts/redis-brain.coffee
@@ -34,12 +34,21 @@
       if err
         throw err
       else if reply
+        robot.logger.info "Brain data retrieved from redis-brain storage"
         robot.brain.mergeData JSON.parse(reply.toString())
       else
         robot.logger.info "Initializing new redis-brain storage"
         robot.brain.mergeData {}

+      robot.logger.info "Enabling brain auto-saving"
+      robot.brain.setAutoSave true
+
+  # Prevent autosaves until connect has occured
+  robot.logger.info "Disabling brain auto-saving"
+  robot.brain.setAutoSave false
+
   robot.brain.on 'save', (data = {}) ->
+    robot.logger.debug "Saving brain data"
     client.set 'hubot:storage', JSON.stringify data

   robot.brain.on 'close', ->


more robust data url detection

more robust data url detection

--- src/core/methods/process/data.coffee
+++ src/core/methods/process/data.coffee
@@ -3,10 +3,13 @@

   vars.history.reset() if vars.history

-  if typeof value is "string"
+  if value.constructor is String
     if value.indexOf("/") >= 0
       method.url = value
       return []
-    if d3.selectAll(value).size() then d3.selectAll(value) else []
+    elem = d3.selectAll(value)
+    return elem if elem.size()
+    method.url = value if value.indexOf(".") >= 0
+    return []
   else
     value


Modify general test.

Modify general test.

--- test/2.general.coffee
+++ test/2.general.coffee
@@ -628,6 +628,9 @@
             ]
         """)
     ).after((v) ->
+        console.log(v.var1)
+        v.var1 = null
+        console.log(v.var1)
         console.log("******************all ended!")
     ).run()
 )


Wait longer to clear preserved lines after mousewheel events

--- src/editor-component.coffee
+++ src/editor-component.coffee
@@ -260,7 +260,7 @@
     # after mousewheel events stop being fired. Removing the target before then
     # will cause scrolling to stop suddenly.
     @visibleRowOverrides = @getVisibleRowRange()
-    @clearVisibleRowOverridesAfterDelay ?= debounce(@clearVisibleRowOverrides, 40)
+    @clearVisibleRowOverridesAfterDelay ?= debounce(@clearVisibleRowOverrides, 100)
     @clearVisibleRowOverridesAfterDelay()

     @refs.verticalScrollbar.getDOMNode().scrollTop -= event.wheelDeltaY


Preserve session ID on page load (#6254)

Use `getSessionID()`, instead of `generateSessionID()`, to preserve any existing session ID when the page first loads.

--- app/partials/app.cjsx
+++ app/partials/app.cjsx
@@ -7,7 +7,7 @@
 `import AppStatus from './app-status';`
 IOStatus = require './io-status'
 AppLayout = require('../layout').default
-{generateSessionID} = require '../lib/session'
+{getSessionID} = require '../lib/session'
 NotificationsCounter = require('../lib/notifications-counter').default
 apiClient = require 'panoptes-client/lib/api-client'

@@ -54,7 +54,7 @@

     auth.listen 'change', @handleAuthChange
     @handleAuthChange()
-    generateSessionID()
+    getSessionID()

   componentDidUpdate: (prevProps) ->
     if prevProps.params isnt @props.params


removed unused file

removed unused file

--- app/scripts/hello.coffee
+++ app/scripts/hello.coffee
@@ -1 +0,0 @@
-console.log "'Allo from CoffeeScript!"


piping starts the stream, no need to read to get things started

--- src/generate-package.coffee
+++ src/generate-package.coffee
@@ -64,14 +64,12 @@
         hash = crypto.createHash 'sha256'
         hash.on 'error', (err) ->
           error "Error getting hash for #{name}-#{version}: #{err}"
-        readHash = ->
+        res.pipe hash
+        hash.on 'readable', ->
           hashBuffer = hash.read 32
           if hashBuffer?
             hashes["#{name}-#{version}"] = hashBuffer
             handleHash()
-        res.pipe hash
-        hash.on 'readable', readHash
-        readHash()

   if name of pkginfos
     handleInfo()


Updating

Updating

--- keymap.cson
+++ keymap.cson
@@ -3,6 +3,7 @@
   "shift-ctrl-C": "terminal-plus:copy"
   "shift-ctrl-K": "markdown-writer:insert-link"
   "shift-ctrl-I": "markdown-writer:insert-image"
+  "ctrl-alt-1":   "package-sync:sync"
   "ctrl-b":       "markdown-writer:toggle-bold-text"
   "ctrl-'":       "markdown-writer:toggle-code-text"
   "ctrl-h":       "markdown-writer:toggle-strikethrough-text"


Add buffer-row data to gutter-component

Add buffer-row data to gutter-component

--- src/gutter-component.coffee
+++ src/gutter-component.coffee
@@ -131,7 +131,7 @@
       style = "visibility: hidden;"
     innerHTML = @buildLineNumberInnerHTML(bufferRow, softWrapped, maxLineNumberDigits)

-    "
#{innerHTML}
"
+    "
#{innerHTML}
"

   buildLineNumberInnerHTML: (bufferRow, softWrapped, maxLineNumberDigits) ->
     if softWrapped


Remove redundant require

Remove redundant require

--- src/gutter-component.coffee
+++ src/gutter-component.coffee
@@ -1,7 +1,6 @@
 _ = require 'underscore-plus'
 React = require 'react-atom-fork'
 {div} = require 'reactionary-atom-fork'
-_ = require 'underscore-plus'
 {isEqual, isEqualForProperties, multiplyString, toArray} = _
 Decoration = require './decoration'
 SubscriberMixin = require './subscriber-mixin'


Fix [ #315929 ] Regression: RTE: incremental="true" having no effect

--- src/resources-packaged/ops/javascript/orbeon/xforms/control/RTE.coffee
+++ src/resources-packaged/ops/javascript/orbeon/xforms/control/RTE.coffee
@@ -32,8 +32,8 @@
         # event is received.
         containerId = @container.id
         registerChangeEvent = () =>
-            @yuiRTE.on "editorKeyUp", () => @changeEvent
-            @yuiRTE.on "afterNodeChange", () => @changeEvent
+            @yuiRTE.on "editorKeyUp", () => @changeEvent()
+            @yuiRTE.on "afterNodeChange", () => @changeEvent()
             @yuiRTE.on "editorWindowFocus", () => Events.focus { target: @container }
             @yuiRTE.on "editorWindowBlur", () => Events.blur { target: @container }
             @yuiRTE.removeListener "afterNodeChange", registerChangeEvent
@@ -64,7 +64,7 @@

     # Event handler called by the RTE every time there is an event which can could potentially change the content
     # of the editor.
-    changeEvent = (controlID) ->
+    changeEvent: (controlID) ->
         # Simulate keyup
         currentFocusControlId = ORBEON.xforms.Globals.currentFocusControlId
         Events.keydown { target: OD.get(currentFocusControlId) }


Updates car using grid width/height

Updates car using grid width/height

--- coffee/game/car.coffee
+++ coffee/game/car.coffee
@@ -68,13 +68,14 @@

     callback = () => @_moveTo(target)

-    neighborhoodLimit = @grid.getBlockSize() - @grid.getStreetSize() / 2
+    neighborhoodWidthLimit = @grid.getBlockWidth() - @grid.getStreetSize() / 2
+    neighborhoodHeightLimit = @grid.getBlockHeight() - @grid.getStreetSize() / 2

     verticalMove = () =>
       nextPosition = null
       orientation = null

-      statement = Math.abs(target.getY() - @currentPosition.getY()) < neighborhoodLimit
+      statement = Math.abs(target.getY() - @currentPosition.getY()) < neighborhoodHeightLimit
       statement &= DoubleHelper.compare(target.getX(), @currentPosition.getX())
       if statement
         nextPosition = target
@@ -97,7 +98,7 @@
       nextPosition = null
       orientation = null

-      statement = Math.abs(target.getX() - @currentPosition.getX()) < neighborhoodLimit
+      statement = Math.abs(target.getX() - @currentPosition.getX()) < neighborhoodWidthLimit
       statement &= DoubleHelper.compare(target.getY(), @currentPosition.getY())
       if statement
         nextPosition = target
@@ -127,9 +128,9 @@
       else if DoubleHelper.compare(target.getY(), @currentPosition.getY())
         # Same horizontal alignment
         horizontalMove()
-      else if Math.abs(target.getX() - @currentPosition.getX()) < neighborhoodLimit
+      else if Math.abs(target.getX() - @currentPosition.getX()) < neighborhoodWidthLimit
         verticalMove()
-      else if Math.abs(target.getY() - @currentPosition.getY()) < neighborhoodLimit
+      else if Math.abs(target.getY() - @currentPosition.getY()) < neighborhoodHeightLimit
         horizontalMove()
       else
         shouldMoveHorizontal = Math.round(Math.random()) is 0


bugfix

bugfix

--- views/components/ship-parts/panebody.cjsx
+++ views/components/ship-parts/panebody.cjsx
@@ -93,11 +93,6 @@
             label[i] = 1
             updateflag = true
     if updateflag
-      try
-        window.setMiniPaneState
-          label: label
-      catch error
-        console.error error
       @setState
         label: label
   shouldComponentUpdate: (nextProps, nextState) ->


require router

require router

--- lib/generators/templates/app.js.coffee
+++ lib/generators/templates/app.js.coffee
@@ -5,6 +5,7 @@
 #= require_tree ./helpers
 #= require_tree ./templates
 #= require_tree ./routes
+#= require ./router
 #= require_self

 <%= application_name.camelize %>.initialize()


add warning line saying that the action is irreversible

--- imports/ui/menus/AppControls.cjsx
+++ imports/ui/menus/AppControls.cjsx
@@ -33,6 +33,7 @@
         <Heading>Remove</Heading>
         <FormFields>
           <Paragraph>Are you sure you want to remove {@props.name}?</Paragraph>
+          <Paragraph>This action is irreversable.</Paragraph>
         </FormFields>

           <Button onClick={@removeApp} secondary=true label='Yes, remove it' />


Added loggedin hook to game#play

Added loggedin hook to game#play

--- app/lib/router.coffee
+++ app/lib/router.coffee
@@ -15,6 +15,7 @@

 Router._filters =
   ganalytics: (pause) -> GAnalytics.pageview()
+
   isLoggedIn: (pause) ->
     loginRedirectKey = 'loginRedirect'

@@ -154,9 +155,18 @@
           Session.set 'currentGameId', id

       onBeforeAction: (pause) ->
-        unless @params.action in ['play', 'result']
-          @render 'notFound'
-          pause()
+        switch @params.action
+          when 'play'
+            unless Meteor.userId()
+              @redirect 'login'
+              FlashMessages.sendWarning 'Du er ikke logget ind'
+              pause()
+
+          when 'result' then break
+
+          else
+            @render 'notFound'
+            pause()

       action: ->
         @render @params.action


Added : dashboard logic

Added : dashboard logic

--- app/lib/router.coffee
+++ app/lib/router.coffee
@@ -4,7 +4,7 @@
 AboutView = require 'views/about-view'
 ContactView = require 'views/contact-view'
 SigninView = require 'views/signin-view'
-
+#async = require 'async'
 TemperatureView = require 'views/temperature-view'
 TemperatureCollectionView = require 'views/temperature-collectionview'
 TemperatureModel = require 'models/temperature-model'
@@ -66,6 +66,40 @@

   dashboard: =>
+    sensorCollection = new TemperatureCollection
+    sensorModels = [ "temperature", "door"]
+
+    sensorModels.forEach(
+      (sensorModel, callback) ->
+        console.log(sensorModel)
+        sensorCollection.fetch(
+          success : ->
+
+
+
+            if(sensorModel == 'temperature')
+              filteredCollection = new TemperatureCollection(
+                sensorCollection.filter(
+                  (sensor)->
+                    sensor.get('model') == sensorModel
+                )
+              )
+              view = new TemperatureCollectionView(collection : filteredCollection)
+              application.layout.contentTemperature.show(view)
+            else
+              filteredCollection = new DoorCollection(
+                sensorCollection.filter(
+                  (sensor)->
+                    sensor.get('model') == sensorModel
+                )
+              )
+              view = new DoorCollectionView(collection : filteredCollection)
+              application.layout.contentDoor.show(view)
+        )
+
+    )
+
+   """
     temperatureModel1 = new TemperatureModel
       room : "Bathroom"
       temperature : "27°C"
@@ -93,7 +127,7 @@
           name: 'Dashboard'
           time: moment().format('MMMM Do YYYY, h:mm:ss a')
       )
-
+"""
   temperature: =>

     sensorCollection = new TemperatureCollection
@@ -114,5 +148,3 @@
               time: moment().format('MMMM Do YYYY, h:mm:ss a')
           )
     )
-
->>>>>>> Added : connect Backbone model's to the REST API and render data


remove unused import

remove unused import

--- js/src/http/KeyStorageApi.coffee
+++ js/src/http/KeyStorageApi.coffee
@@ -22,7 +22,6 @@

   # Kryptnostic
   BlockCiphertext = require 'kryptnostic.block-ciphertext'
-  CredentialLoader = require 'kryptnostic.credential-loader'

   # utils
   BinaryUtils = require 'kryptnostic.binary-utils'


add discount feature and add show someone's category deatail. close #8

--- src/hubot-order-menu.coffee
+++ src/hubot-order-menu.coffee
@@ -20,6 +20,7 @@
 # hubot order reset @someone - reset someone orders.
 # hubot order reset my - reset your orders.
 # hubot order reset category <category> - clear category.
+# hubot order set discount <category> - setting category's discount.
 #
 # Author:
 #   Ghost.Yang
@@ -53,7 +54,6 @@
     Send: ->
       message = @commands.join('\n')
       @bot.reply message
-

   unless process.env.HUBOT_ORDER_MENU_STORE_INFO?
     robot.logger.warning 'The HUBOT_ORDER_MENU_STORE_INFO environment variable not set'
@@ -265,6 +265,10 @@
       msg.reply "you reset category #{_categoryName} !"
       delete robot.brain.data.order[_categoryName]

+  robot.respond /order set discount (\S*)/i, (msg) ->
+    discount = msg.match[1]
+
+
   parseTarget = (text) ->
     robot.logger.warning text
     regexPattern = /order (.* for |reset )\<@?(\S*)\>/i


payment: code style (whitespace)

payment: code style (whitespace)

--- node_modules_koding/koding-payment/lib/main.coffee
+++ node_modules_koding/koding-payment/lib/main.coffee
@@ -454,7 +454,8 @@
         return callback err  if err
         callback null, accObj res[0]?.account, billing

-  @setAccountDetailsByAccountCode: (accountCode, data, callback)->
+  @setAccountDetailsByAccountCode: (accountCode, data, callback) ->
+
     xml =
       """
       <?xml version="1.0" encoding="UTF-8"?>


Set back to play full game

Set back to play full game

--- src/scenes/Intro.coffee
+++ src/scenes/Intro.coffee
@@ -59,7 +59,7 @@
   Crafty('Player').each ->
     @reset()
     @one 'Activated', ->
-      Crafty.enterScene(Game.firstLevel, script: Test) # checkpoint: value
+      Crafty.enterScene(Game.firstLevel)

   Crafty.e('Delay').delay ->
       Crafty.enterScene('Scores')


use "reply" instead of "send"

use "reply" instead of "send"

--- src/scripts/dice.coffee
+++ src/scripts/dice.coffee
@@ -6,7 +6,7 @@

 module.exports = (robot) ->
   robot.respond /roll dice/i, (msg) ->
-    msg.send report roll 2, 6
+    msg.reply report roll 2, 6
   robot.respond /roll (\d+)d(\d+)/i, (msg) ->
     dice = parseInt msg.match[1]
     sides = parseInt msg.match[2]
@@ -16,7 +16,7 @@
       "I'm not going to roll more than 100 dice for you."
     else
       report roll dice, sides
-    msg.send answer
+    msg.reply answer

 report = (results) ->
   if results?


allow help to search help commands

allow help to search help commands

--- src/scripts/help.coffee
+++ src/scripts/help.coffee
@@ -3,8 +3,12 @@
 # These commands are grabbed from comment blocks at the top of each file.
 #
 # help - Displays all of the help commands that Hubot knows about.
+# help <query> - Displays all help commands that match <query>.

 module.exports = (robot) ->
-  robot.respond /help$/i, (msg) ->
-    msg.send robot.helpCommands().join("\n")
+  robot.respond /help\s*(.*)?$/i, (msg) ->
+    cmds = robot.helpCommands()
+    if msg.match[1]
+      cmds = cmds.filter (cmd) -> cmd.match(new RegExp(msg.match[1]))
+    msg.send cmds.join("\n")


Give the help route some styling

Give the help route some styling

--- src/scripts/help.coffee
+++ src/scripts/help.coffee
@@ -5,8 +5,50 @@
 #   hubot help - Displays all of the help commands that Hubot knows about.
 #   hubot help <query> - Displays all help commands that match <query>.
 #
+# URLS:
+#   /hubot/help
+#
 # Notes:
 #   These commands are grabbed from comment blocks at the top of each file.
+
+helpContents = (name, commands) ->
+
+  """
+
+
+  <title>#{name} Help</title>
+
+
+
+
#{name} Help

+

+      #{commands}
+

+
+
+  """

 module.exports = (robot) ->
   robot.respond /help\s*(.*)?$/i, (msg) ->
@@ -19,11 +61,15 @@
     emit = cmds.join "\n"

     unless robot.name.toLowerCase() is 'hubot'
-      emit = emit.replace /(H|h)ubot/g, robot.name
+      emit = emit.replace /hubot/ig, robot.name

     msg.send emit

   robot.router.get '/hubot/help', (req, res) ->
     cmds = robot.helpCommands()
+    emit = "
#{cmds.join '

'}
"
+
+    emit = emit.replace /hubot/ig, "#{robot.name}"
+
     res.setHeader 'content-type', 'text/html'
-    res.end cmds.join '
'
+    res.end helpContents robot.name, emit


tell.coffee: Use current recipient name

tell.coffee: Use current recipient name

Address the recipient by his current username when delivering messages. As prefix matching is applied to recipients' names, it is  insufficient to address the user by the prefix, as their client most likely will not issue a highlight this way.

--- src/scripts/tell.coffee
+++ src/scripts/tell.coffee
@@ -19,7 +19,7 @@
      datetime = new Date()
      username = msg.match[1]
      room = msg.message.user.room
-     tellmessage = username + ": " + msg.message.user.name + " @ " + datetime.toLocaleString() + " said: " + msg.match[2] + "\r\n"
+     tellmessage = msg.message.user.name + " @ " + datetime.toLocaleString() + " said: " + msg.match[2] + "\r\n"
      if not localstorage[room]?
        localstorage[room] = {}
      if localstorage[room][username]?
@@ -36,7 +36,7 @@
        for recipient, message of localstorage[room]
          # Check if the recipient matches username
          if username.match(new RegExp "^"+recipient, "i")
-           tellmessage = localstorage[room][recipient]
+           tellmessage = username + ": " + localstorage[room][recipient]
            delete localstorage[room][recipient]
            msg.send tellmessage
      return


Finish gospers glider gun for twoD arrays


install pods

install pods

--- main.coffee
+++ main.coffee
@@ -53,6 +53,11 @@
     execSync "#{ binPath }react-native init #{ projName }"
     execSync "mv #{ projName } iOS"

+    log 'Installing Pod dependencies'
+    process.chdir 'iOS'
+    execSync "cp #{ resources }Podfile ."
+    execSync 'pod install'
+
   catch e
     logErr e.message


:basketball::shoe: Updated in browser at strd6.github.io/editor

--- main.coffee
+++ main.coffee
@@ -17,7 +17,7 @@
   cmd = msg >> 4
   channel = msg & 0xf
   type = msg & 0xf0
-
+
   console.log event.data

   switch type
@@ -25,7 +25,7 @@
       state.toSet = note
       state.moveNext = 2

-      playNote(note, note)
+      playNote(note, velocity, note)
     when 128 # Note off
       releaseNote(note)

@@ -82,8 +82,8 @@
 updateViz = ->
   viz.draw(canvas)

-  trackTime = (t / 4) % 1
-  track.draw(canvas, trackTime, state)
+  # trackTime = (t / 4) % 1
+  # track.draw(canvas, trackTime, state)

   requestAnimationFrame updateViz

@@ -151,7 +151,7 @@
   noteFrequencies[note]

 notes = {}
-playNote = (note, id) ->
+playNote = (note, velocity, id) ->
   # TODO: Why do these notes cut out suddenly and for no reason?
   console.log "play!"
   freq = noteToFreq(note - 12)
@@ -161,9 +161,9 @@
   osco.frequency.value = freq

   osco = Gainer(osco)
-  osco.gain.linearRampToValueAtTime(1, context.currentTime)
+  osco.gain.linearRampToValueAtTime(velocity / 128, context.currentTime)
   osco.connect(masterGain)
-
+
   osco.start(context.currentTime)

   notes[id] = [osco, osco.gain]
@@ -172,7 +172,7 @@
   console.log "release!"
   [osco, gain] = notes[id]
   # Wow this is nutz!
-  # Need to set the value to the current value because the
+  # Need to set the value to the current value because the
   # linearRampToValueAtTime uses the previous time to create the ramp, yolo!
   gain.setValueAtTime(osco.gain.value, context.currentTime)
   gain.linearRampToValueAtTime(0.0, context.currentTime + 0.125)


fix beer-song tests

fix beer-song tests

--- exercises/beer-song/beer-song.spec.coffee
+++ exercises/beer-song/beer-song.spec.coffee
@@ -28,7 +28,6 @@

     6 bottles of beer on the wall, 6 bottles of beer.
     Take one down and pass it around, 5 bottles of beer on the wall.
-
     '

   xit 'sings the rest of the verses', ->
@@ -44,12 +43,4 @@

     No more bottles of beer on the wall, no more bottles of beer.
     Go to the store and buy some more, 99 bottles of beer on the wall.
-
-<<<<<<< HEAD:exercises/beer-song/beer-song.spec.coffee
     '
-=======
-    """
-<<<<<<< HEAD:exercises/beer-song/beer-song.spec.coffee
->>>>>>> beer-song stub file:exercises/beer-song/beer-song_test.spec.coffee
-=======
->>>>>>> b04a45190849e2f4cb3f56024234c4da51df9ab7:exercises/beer-song/beer-song_test.spec.coffee


social: jcampaigndata campaign info made required

--- workers/social/lib/social/models/campaigndata.coffee
+++ workers/social/lib/social/models/campaigndata.coffee
@@ -10,6 +10,7 @@
         validate : require('./name').validateEmail
         set      : (value) -> value.toLowerCase()
       campaign   :
+        required : yes
         type     : String
       username   :
         type     : String


OnigRegExp.getCaptureTree does not include empty child captures

--- src/stdlib/onig-reg-exp.coffee
+++ src/stdlib/onig-reg-exp.coffee
@@ -9,7 +9,8 @@

     childCaptures = []
     while startPositions[0] < endPosition
-      childCaptures.push(buildCaptureTree(captures, startPositions, totalCaptures))
+      subtree = buildCaptureTree(captures, startPositions, totalCaptures)
+      childCaptures.push(subtree) if subtree.text.length

     tree.captures = childCaptures if childCaptures.length
     tree


Restyled some code, per @markijbema's comment

--- js-library/app/js/util/scrollto.coffee
+++ js-library/app/js/util/scrollto.coffee
@@ -1,13 +1,10 @@
 Factlink.scrollTo = (fact_id) ->
   $('body')
     ._scrollable()
-    .scrollTo(
-      "span[data-factid=#{fact_id}]",
-      800,
+    .scrollTo "span[data-factid=#{fact_id}]", 800,
       offset:
         top:-100
         axis: 'y'
-    )

 $(window).bind 'factlink.factsLoaded', ->
   if Factlink? and FactlinkConfig? and FactlinkConfig.scrollto


Non-PHP `/profile/`.

Non-PHP `/profile/`.

--- main.coffee
+++ main.coffee
@@ -158,7 +158,21 @@
 		response.render 'login', options

-app.get '/profile/', phpgate # PHP
+app.get '/profile/', (request, response) -> sync ->
+	if request.uonline.basicOpts.loggedIn is true
+		options = request.uonline.basicOpts
+		options.instance = 'profile'
+		options.nickname = request.uonline.basicOpts.login
+		options.profileIsMine = true
+		options.id = request.uonline.basicOpts.userid
+		chars = utils.game.getUserCharacters.sync null, mysqlConnection, request.uonline.basicOpts.userid
+		for i of chars
+			options[i] = chars[i]
+		response.render 'profile', options
+	else
+		response.redirect '/login/'
+
+
 app.get '/profile/id/:id/', phpgate # PHP
 app.get '/profile/user/:user/', phpgate # PHP


support React Native 0.11

support React Native 0.11

--- main.coffee
+++ main.coffee
@@ -10,16 +10,15 @@
 cli        = require 'commander'
 chalk      = require 'chalk'
 semver     = require 'semver'
-reactInit  = require 'react-native/local-cli/init'
 pkgJson    = require __dirname + '/package.json'

 nodeVersion     = pkgJson.engines.node
-rnVersion       = pkgJson.dependencies['react-native']
 resources       = __dirname + '/resources/'
 camelRx         = /([a-z])([A-Z])/g
 projNameRx      = /\$PROJECT_NAME\$/g
 projNameHyphRx  = /\$PROJECT_NAME_HYPHENATED\$/g
 projNameUnderRx = /\$PROJECT_NAME_UNDERSCORED\$/g
+rnVersion       = '0.11.4'
 podMinVersion   = '0.38.2'
 process.title   = 'natal'

@@ -82,9 +81,9 @@

 getBundleId = (name) ->
   try
-    if line = readFile("iOS/iOS/#{name}.xcodeproj/project.pbxproj").match /PRODUCT_BUNDLE_IDENTIFIER = (.+);/
+    if line = readFile("native/ios/#{name}.xcodeproj/project.pbxproj").match /PRODUCT_BUNDLE_IDENTIFIER = (.+);/
       line[1]
-    else if line = readFile("iOS/iOS/#{name}/Info.plist").match /\<key\>CFBundleIdentifier\<\/key\>\n?\s*\<string\>(.+)\<\/string\>/
+    else if line = readFile("native/ios/#{name}/Info.plist").match /\<key\>CFBundleIdentifier\<\/key\>\n?\s*\<string\>(.+)\<\/string\>/
       rfcIdRx = /\$\(PRODUCT_NAME\:rfc1034identifier\)/

       if line[1].match rfcIdRx
@@ -140,12 +139,9 @@
     exec 'lein cljsbuild once dev'

     log 'Creating React Native skeleton'
-    fs.mkdirSync 'iOS'
-    process.chdir 'iOS'
-    _log = console.log
-    global.console.log = ->
-    reactInit '.', projName
-    global.console.log = _log
+    fs.mkdirSync 'native'
+    process.chdir 'native'
+
     fs.writeFileSync 'package.json', JSON.stringify
       name:    projName
       version: '0.0.1'
@@ -155,10 +151,19 @@
       dependencies:
         'react-native': rnVersion
     , null, 2
+
     exec 'npm i'
+    exec "
+         node -e
+         \"process.argv[3]='#{projName}';
+         require('react-native/local-cli/init')('.', '#{projName}')\"
+         "
+
+    exec 'rm -rf android'
+    fs.unlinkSync 'index.android.js'

     log 'Installing Pod dependencies'
-    process.chdir 'iOS'
+    process.chdir 'ios'
     exec "cp #{resources}Podfile ."
     exec 'pod install'

@@ -194,7 +199,7 @@
         [
           /\/\* End PBXFileReference section \*\//
           "\t\t#{uuid1} /* out */ = {isa = PBXFileReference; lastKnownFileType
-           = folder; name = out; path = ../../../target/out;
+           = folder; name = out; path = ../../target/out;
            sourceTree = \"<group>\"; };\n/* End PBXFileReference section */"
         ]
         [
@@ -269,11 +274,11 @@

 launch = ({name, device}) ->
-  log 'Building Xcode project'
+  log 'Compiling Xcode project'
   try
     exec "
          xcodebuild
-         -workspace iOS/iOS/#{name}.xcworkspace
+         -workspace native/ios/#{name}.xcworkspace
          -scheme #{name}
          -destination platform='iOS Simulator',OS=latest,id='#{device}'
          clean test
@@ -288,16 +293,16 @@

 openXcode = (name) ->
   try
-    exec "open iOS/iOS/#{name}.xcworkspace"
+    exec "open native/ios/#{name}.xcworkspace"
   catch {message}
     logErr \
       if message.match /ENOENT/i
         """
-        Cannot find #{name}.xcworkspace in iOS/iOS.
+        Cannot find #{name}.xcworkspace in native/ios.
         Run this command from your project's root directory.
         """
       else if message.match /EACCES/i
-        "Invalid permissions for opening #{name}.xcworkspace in iOS/iOS"
+        "Invalid permissions for opening #{name}.xcworkspace in native/ios"
       else
         message


Delete main.coffee

Delete main.coffee

--- main.coffee
+++ main.coffee
@@ -1,233 +0,0 @@
-VISIBLE_ZEROS = true
-class Polynomial
-	constructor:(@degree = 0, @field = 2, @coeff = [0])->
-		@coeff.length = @degree + 1
-		do @fieldify
-
-	fieldify: ->
-		for elem, index in @coeff
-			if elem
-				elem %= @field
-				elem += @field if elem < 0
-			else
-				elem = 0
-			@coeff[index] = elem
-		return @
-
-	normalize: ->
-		do @fieldify
-		while @degree
-			break if @coeff[@degree]
-			@degree--
-			@coeff.length--
-		return @
-
-	toStringpolynomial: ->
-		result = ""
-		index = @degree
-		while index >= 0
-			cur = @coeff[index]
-			if result
-				if cur or VISIBLE_ZEROS
-					result += " + "
-			if cur or VISIBLE_ZEROS
-				if index == 0
-					result += cur
-				else
-					result += "#{cur}x^#{index}^"
-			index--
-		return result
-
-	equal: (polynomial) ->
-		@degree = polynomial.degree
-		@field = polynomial.field
-		for elem, index in polynomial.coeff
-			@coeff = elem
-		return @
-
-	add: (polynomial) ->
-		if @field isnt polynomial.field
-			console.log "Error: Attempt to realize [ADDITION] in different fields"
-			return @
-
-		a       = @coeff
-		b       = polynomial.coeff
-		deg     = Math.max @degree, polynomial.degree
-		result  = new Polynomial deg, @field
-		rc      = result.coeff
-
-		for elem, index in result.coeff
-			rc[index] = a[index] + b[index]
-
-		do result.normalize
-
-	substract: (polynomial) ->
-		if @field isnt polynomial.field
-			console.log "Error: Attempt to realize [SUBSTRACTION] in different fields"
-			return @
-
-		a       = @coeff
-		b       = polynomial.coeff
-		deg     = Math.max @degree, polynomial.degree
-		result  = new Polynomial deg, @field
-		rc      = result.coeff
-
-		for elem, index in result.coeff
-			if not a[index]
-				rc[index] = -b[index]
-			else if not b[index]
-				rc[index] = a[index]
-			else
-				rc[index] = a[index] - b[index]
-
-		do result.normalize
-
-	multiply: (polynomial) ->
-		if @field isnt polynomial.field
-			console.log "Error: Attempt to realize [MULTIPLICATION] in different fields"
-			return @
-
-		result  = new Polynomial (@degree + polynomial.degree), @field
-		rc      = result.coeff
-
-		for elem1, index1 in @coeff
-			for elem2, index2 in polynomial.coeff
-				continue if not elem1 or not elem2
-
-				rc[index1 + index2] += elem1 * elem2
-
-		return do result.normalize
-
-	_scalarMultiply: (scalar) ->
-		result = new Polynomial
-		result.equal @
-		rc = result.coeff
-
-		for elem, index in result.coeff
-			rc = elem * scalar
-
-		do result.fieldify
-
-	_powerShift: (pow) ->
-		return @ if pow <= 0
-
-		result = new Polynomial
-		result.equal @
-		result.degree += pow
-		rc = result.coeff
-
-		while pow
-			rc.unshift 0
-			pow--
-
-		do result.normalize
-
-	divide: (polynomial) ->
-		logging = false
-		if logging
-			tmp = VISIBLE_ZEROS
-			VISIBLE_ZEROS = true
-		if @field isnt polynomial.field
-			console.log "Error: Attempt to realize [DIVISION] in different fields"
-			return @
-		if @degree < polynomial.degree
-			zero = new Polynomial()
-			return zero
-
-		do @normalize
-		do polynomial.normalize
-
-		result  = new Polynomial (polynomial.degree - 1), @field
-		a       = new Polynomial
-		b       = new Polynomial
-		index1  = a.degree
-		index2  = 0;
-
-		a.equal @
-
-		if logging
-			console.log do @toStringpolynomial
-			console.log ("=======================================");
-		while index1 > result.degree
-			continue if not a.coeff[index1]
-
-			b.equal polynomial
-
-			index2 = 0
-			while index2 < @field
-				b.equal(polynomial._scalarMultiply index2)
-				index2++
-				break if b.coeff[b.degree] == a.coeff[index1]
-
-
-			result.coeff[a.degree - polynomial.degree] = index2
-			b.equal(b._powerShift(index1 - polynomial.degree))
-			a.equal(a.substract b)
-			a.fieldify
-			if logging
-				console.log "-"
-				console.log do b.toStringpolynomial
-				console.log "---------------------------------------"
-				console.log do a.toStringpolynomial
-			index1--
-
-		if logging
-			VISIBLE_ZEROS = tmp;
-			console.log "\nResult: #{do result.toStringpolynomial}"
-			console.log "\nReminder: #{do a.toStringpolynomial}"
-
-		do result.normalize
-
-	parse:(inputStr) ->
-		# 5x^3^ + 3x^2^ + 0x^1^ + 7^x^ + 5
-		result = new Polynomial 0, @field
-		try
-			while true
-				cur = parseInt inputStr, 10
-				throw 1 if cur == NaN
-				console.log "Current coeff: #{cur}"
-				inputStr = inputStr.slice (inputStr.indexOf "x^") + 2
-				console.log "Sliced string: #{inputStr}"
-				deg = parseInt inputStr, 10
-				console.log "Current degree: #{deg}"
-				inputStr = inputStr.slice (inputStr.indexOf "+") + 2
-				console.log "Sliced string: #{inputStr}"
-
-				if deg = NaN
-					if inputStr.indexOf "+" == -1
-						result.coeff[0] = cur
-					else
-						throw 2
-				else
-					result.coeff[deg] = cur
-				if inputStr.indexOf "+" == -1
-					break
-
-		catch e
-			if e == 1
-				console.log "Error: Bad coefficient
-				\nCheck 'HELP' for instructions."
-				return -1;
-			if e == 2
-				console.log "Error: Bad degree
-				\nCheck 'HELP' for instructions."
-				return -1;
-		return @
-
-#=====================
-# DEBUG
-#=====================
-test1   = new Polynomial 5,3,[1,2,3,4,5,6]
-# test2 = new Polynomial 5,3,[9,8,7]
-# console.log do test1.toStringpolynomial
-# console.log do test2.toStringpolynomial
-# console.log ""
-# console.log "sum: #{do test1.add(test2).toStringpolynomial}"
-# console.log "substract: #{do test1.substract(test2).toStringpolynomial}"
-# console.log "multiply: #{do test1.multiply(test2).toStringpolynomial}"
-# console.log "divide: #{do test1.divide(test2).toStringpolynomial}" #DEBUG!!! ALWAYS RETURNS 0
-
-testStr = "5x^3^ + 3x^2^ + 0x^1^ + 7^x^ + 5"
-
-test1.parse testStr
-


Improved log function

Improved log function

--- main.coffee
+++ main.coffee
@@ -320,7 +320,6 @@
             else
                 callback(null, 'OK')

-    log: (msg) -> console.log msg unless @silent
-
+    log: -> console.log.apply console, arguments unless @silent

 module.exports = new FixtureManager()


Add sanitize-email command to run script

--- config/main.dev.coffee
+++ config/main.dev.coffee
@@ -1187,6 +1187,7 @@
         echo "  run supervisor [env]      : to show status of workers in that environment"
         echo "  run migrate [command]     : to apply/revert database changes (command: [create|up|down|version|reset|redo|to|goto])"
         echo "  run importusers           : to import koding user data"
+        echo "  run sanitize-email        : to sanitize email"
         echo "  run help                  : to show this list"
         echo ""

@@ -1685,6 +1686,9 @@
       elif [ "$1" == "nodetestfiles" ]; then
         #{projectRoot}/scripts/node-testing/mocha-runner $2

+      elif [ "$1" == "sanitize-email" ]; then
+        node #{projectRoot}/scripts/sanitize-email
+
       else
         echo "Unknown command: $1"
         printHelp


Fix field lookup, hopefully for real this time.

`javap -c` should work now. I would add a test, but I can't seem to
reproduce it in a small test file...

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -188,6 +188,7 @@
           @method_lookup({'class': cls, 'sig': {'name': 'initializeSystemClass'}}).run(this)
         util.log_level = old_loglevel  # resume logging
     c = @classes[cls]
+  # spec 5.4.3.3, 5.4.3.4
   method_lookup: (method_spec) ->
     filter_methods = (cls) ->
       ms = (m for m in cls.methods when m.name is method_spec.sig.name)
@@ -213,20 +214,25 @@
         (c2t(ifc.constant_pool.get(i).deref()) for i in ifc.interfaces)
     java_throw @, 'java/lang/NoSuchMethodError',
       "No such method found in #{method_spec.class}: #{method_spec.sig.name}::#{method_spec.sig.type}"
+  # spec 5.4.3.2
   field_lookup: (field_spec) ->
     filter_field = (c) -> _.find(c.fields, (f)-> f.name is field_spec.sig.name)
-    t = c2t field_spec.class
+    field = @_field_lookup field_spec.class, filter_field
+    return field if field?
+    java_throw @, 'java/lang/NoSuchFieldError',
+      "No such field found in #{field_spec.class}: #{field_spec.sig.name}::#{field_spec.sig.type}"
+  _field_lookup: (class_name, filter_fn) ->
+    t = c2t class_name
     while t
       cls = @class_lookup(t)
-      field = filter_field cls
+      field = filter_fn cls
       return field if field?
-      ifaces = (c2t(cls.constant_pool.get(i).deref()) for i in cls.interfaces)
+      ifaces = (cls.constant_pool.get(i).deref() for i in cls.interfaces)
       for ifc in ifaces
-        field = filter_field @class_lookup ifc
+        field = @_field_lookup ifc, filter_fn
         return field if field?
       t = cls.super_class
-    java_throw @, 'java/lang/NoSuchFieldError',
-      "No such field found in #{field_spec.class}: #{field_spec.sig.name}::#{field_spec.sig.type}"
+    null

   # casting and such
   is_subclass: (class1, class2) ->


Fix selected conv not being saved properly.

--- src/ui/models/viewstate.coffee
+++ src/ui/models/viewstate.coffee
@@ -118,7 +118,9 @@
             conv_id = conv.listShow()?[0]?.conversation_id?.id
         return if @selectedConv == conv_id
         @switchInput(conv_id)
-        @selectedConv = localStorage.selectedConv = conv_id
+        # don't save the selected conv if we don't have a valid input
+        if c?
+            @selectedConv = localStorage.selectedConv = conv_id
         @setLastKeyDown 0
         @updateView()
         updated 'switchConv'


builder: recursively check file case

builder: recursively check file case

This can bite us since stupidly HFS+ is case-insensitive by default.  It occurs when the case of a directory is wrong in the includes file.  It should throw an early error in that case.

--- Builder.coffee
+++ Builder.coffee
@@ -33,6 +33,17 @@
     break unless bytes >= thresh

   return "#{minus}#{bytes.toFixed 2} #{units[unitIndex]}"
+
+checkFileCase = (fileName) ->
+  basename = path.basename fileName
+  dirname  = path.normalize path.dirname fileName
+  listing  = fs.readdirSync dirname
+
+  if basename in listing
+    if (dirname.split '/').length > 1
+    then checkFileCase dirname
+    else yes
+  else no

 module.exports = class Builder

@@ -208,12 +219,11 @@
             cacheTime     : if fs.existsSync(cachePath) then Date.parse(fs.statSync(cachePath).mtime) else 0
             extension     : path.extname(includePath)

-          if not (path.basename(file.sourcePath) in fs.readdirSync(path.dirname(file.sourcePath)))
-            log.error "File name case is wrong: " + includePath
+          if file.sourcePath in @blackList
+            @blackList.splice (@blackList.indexOf file.sourcePath), 1
+          else if not checkFileCase file.sourcePath
+            log.error "File name case is wrong: #{ includePath }"
             process.exit 1
-          else
-            if file.sourcePath in @blackList
-              @blackList.splice (@blackList.indexOf file.sourcePath), 1

           switch file.extension
             when ".coffee", ".js"


set UI to inactive when won

set UI to inactive when won

--- maze.coffee
+++ maze.coffee
@@ -122,6 +122,7 @@
     @busy = false
     @queue = []
     @moves = 0
+    @active = true

     # floor positions
     width = @maze.dimensions[0] * 71 + 1
@@ -262,24 +263,26 @@

     # attach key event handlers
     $(document).keyup((event) =>
+      if !@active
+        return
       if event.which == 82 # R key
         @goUp()
-        @whenIdle(=>@updateMsg())
+        @whenIdle(=>@updateStatus())
       else if event.which == 70 # F key
         @goDown()
-        @whenIdle(=> @updateMsg())
+        @whenIdle(=> @updateStatus())
       else if event.which == 37 # Left key
         @goLeft()
-        @whenIdle(=> @updateMsg())
+        @whenIdle(=> @updateStatus())
       else if event.which == 38 # Up key
         @goForward()
-        @whenIdle(=> @updateMsg())
+        @whenIdle(=> @updateStatus())
       else if event.which == 39 # Right key
         @goRight()
-        @whenIdle(=> @updateMsg())
+        @whenIdle(=> @updateStatus())
       else if event.which == 40 # Down key
         @goBackward()
-        @whenIdle(=> @updateMsg())
+        @whenIdle(=> @updateStatus())
     )

     # messagebox
@@ -357,9 +360,10 @@
           left: @x * 71
     }, 200, callback)

-  updateMsg: ->
+  updateStatus: ->
     if @maze.isFinish([@x, @y, @z])
       msg = MazeUI3D.msg['win']
+      @active = false
     else if @maze.passageExists([[@x, @y, @z], [@x, @y, @z + 1]]) or @maze.passageExists([[@x, @y, @z - 1], [@x, @y, @z]])
       msg = MazeUI3D.msg['updown']
     else


Ensure channel integration specs is always fetchd before doing something

--- src/spec/integration/channels.spec.coffee
+++ src/spec/integration/channels.spec.coffee
@@ -11,6 +11,7 @@
 uniqueId = (prefix) ->
   _.uniqueId "#{prefix}#{new Date().getTime()}_"

+# 'InventorySupply' is provided by default
 newChannel = ->
   key: uniqueId 'c'

@@ -37,27 +38,30 @@
     @client.channels.save(newChannel())
     .then (result) =>
       expect(result.statusCode).toBe 201
-      @channel = result.body
-      @logger.info @channel, 'New channel created'
+      @channelId = result.body.id
+      @logger.info @channel, "New channel created: #{@channelId}"
       done()
     .fail (error) -> done _.prettify(error)

   afterEach (done) ->
-    @client.channels.byId(@channel.id).delete(@channel.version)
+    @client.channels.byId(@channelId).fetch()
     .then (result) =>
-      @logger.info "Channel deleted: #{@channel.id}"
+      @client.channels.byId(@channelId).delete(result.body.version)
+    .then (result) =>
+      @logger.info "Channel deleted: #{@channelId}"
       expect(result.statusCode).toBe 200
       done()
     .fail (error) -> done _.prettify(error)

   it 'should update a channel', (done) ->
-    @client.channels.byId(@channel.id).update(updateChannel(@channel.version))
+    @client.channels.byId(@channelId).fetch()
     .then (result) =>
+      @client.channels.byId(@channelId).update(updateChannel(result.body.version))
+    .then (result) ->
       expect(result.statusCode).toBe 200
-      @channel = result.body
-      expect(@channel.name).toEqual {en: 'A Channel'}
-      expect(@channel.description).toEqual {en: 'This is a Channel'}
-      expect(@channel.roles).toEqual [ROLE_INVENTORY_SUPPLY, ROLE_ORDER_EXPORT]
+      expect(result.body.name).toEqual {en: 'A Channel'}
+      expect(result.body.description).toEqual {en: 'This is a Channel'}
+      expect(result.body.roles).toEqual [ROLE_INVENTORY_SUPPLY, ROLE_ORDER_EXPORT]
       done()
     .fail (error) -> done _.prettify(error)

@@ -65,7 +69,6 @@
     key = uniqueId "channel"
     @client.channels.ensure(key, ROLE_ORDER_EXPORT)
     .then (result) ->
-      channels.push result.body
       expect(result.body).toBeDefined()
       expect(result.body.key).toEqual key
       expect(result.body.roles).toEqual [ROLE_ORDER_EXPORT]
@@ -73,32 +76,21 @@
     .fail (error) -> done _.prettify(error)

   it 'should fetch an existing channel, add given role and return it', (done) ->
-
-    @client.channels.ensure(@channel.key, ROLE_ORDER_EXPORT)
+    @client.channels.byId(@channelId).fetch()
     .then (result) =>
-      @client.channels.ensure(@channel.key, ROLE_PRIMARY)
-      .then (result) ->
-      expect(result.body.roles).toEqual [ROLE_INVENTORY_SUPPLY, ROLE_ORDER_EXPORT]
-      done()
-    .fail (error) -> done _.prettify(error)
-  , 10000 # 10sec
-
-  it 'should fetch an existing channel and return it', (done) ->
-
-    @client.channels.byId(@channel.id).update(updateChannel(@channel.version))
+      @client.channels.ensure(result.body.key, ROLE_ORDER_EXPORT)
     .then (result) =>
-      @channel = result.body
-      @client.channels.ensure(@channel.key, ROLE_ORDER_EXPORT)
-    .then (result) =>
-      expect(result.body).toBeDefined()
-      expect(result.body.id).toEqual @channel.id
-      expect(result.body.roles).toEqual @channel.roles
+      @client.channels.ensure(result.body.key, ROLE_PRIMARY)
+    .then (result) ->
+      expect(result.body.roles).toEqual [ROLE_INVENTORY_SUPPLY, ROLE_ORDER_EXPORT, ROLE_PRIMARY]
       done()
     .fail (error) -> done _.prettify(error)
   , 10000 # 10sec

   it 'should fail if role value is not supported', (done) ->
-    @client.channels.ensure(@channel.key, 'undefined-role')
+    @client.channels.byId(@channelId).fetch()
+    .then (result) =>
+      @client.channels.ensure(result.body.key, 'undefined-role')
     .then (result) ->
       done 'Role value not supported.'
     .fail (error) ->


Improving docs and fixing `reset` method.

--- src/toaster.coffee
+++ src/toaster.coffee
@@ -23,6 +23,7 @@
   before_build: null

   constructor:( basedir, options = null, skip_initial_build = false )->
+
     @basedir = basedir
     @options = options
     @skip_initial_build = skip_initial_build
@@ -78,9 +79,9 @@
     else
       return log @cli.opts.help()

-  # can be called by apps using toaster as lib, build the project with options
-  # to inject header and footer code which must to be in coffee as well and
-  # will be compiled together the app.
+  # can be called by apps using toaster as lib, and build the project with
+  # options to inject header and footer code which must to be in coffee as well
+  # and will be compiled together the app.
   build:( header_code = "", footer_code = "" )->
     for builder in @toast.builders
       builder.build header_code, footer_code
@@ -89,6 +90,5 @@
   # config file is edited :)
   reset:( options )->
     builder.reset() for builder in @toast.builders
-    if options?
-      @options[ key ] = val for val, key of options
-   new Toaster @basedir, @options, @skip_initial_build+    @options[ key ] = val for val, key of options if options?
+    new Toaster @basedir, @options, @skip_initial_build


Fixed inline translations with &, < and > issues.

--- app/assets/javascripts/app/controllers/widget/translation_inline.coffee
+++ app/assets/javascripts/app/controllers/widget/translation_inline.coffee
@@ -34,7 +34,7 @@
     $('body')
       .on 'focus.translation', '.translation', (e) ->
         element = $(e.target)
-        element.data 'before', element.html()
+        element.data 'before', element.text()
         element
       .on 'blur.translation', '.translation', (e) =>
         console.log('blur')
@@ -42,12 +42,7 @@
         source = element.attr('title')

         # get new translation
-        translation_new = element.html()
-        translation_new = ('' + translation_new)
-          .replace(/<.+?>/g, '')
-
-        # set new translation
-        element.html(translation_new)
+        translation_new = element.text()

         # update translation
         return if element.data('before') is translation_new
@@ -58,7 +53,7 @@
         App.i18n.setMap(source, translation_new)

         # replace rest in page
-        $(".translation[title='#{source}']").html(translation_new)
+        $(".translation[title='#{source}']").text(translation_new)

         # update permanent translation mapString
         translation = App.Translation.findByAttribute('source', source)


pass tutorial-toggling props to text tool

--- app/assets/javascripts/components/transcribe/tools/text-tool/index.cjsx
+++ app/assets/javascripts/components/transcribe/tools/text-tool/index.cjsx
@@ -290,6 +290,7 @@
         y={y*@props.scale.vertical + @props.scale.offsetY}
         buttons={buttons}
         classes="transcribe-tool"
+        toggleYaleTutorial={@props.toggleYaleTutorial}
         >

           {tool_content}


Refactor darker-background directive, extract method

--- app/assets/javascripts/darkswarm/directives/darker_background.js.coffee
+++ app/assets/javascripts/darkswarm/directives/darker_background.js.coffee
@@ -1,4 +1,7 @@
 Darkswarm.directive "darkerBackground", ->
   restrict: "A"
   link: (scope, elm, attr)->
-    elm.closest('.page-view').toggleClass("with-darker-background", true)
+    toggleClass = (value) ->
+      elm.closest('.page-view').toggleClass("with-darker-background", value)
+
+    toggleClass(true)


update webpack config and use material-ui

--- build/webpack.config.coffee
+++ build/webpack.config.coffee
@@ -1,7 +1,6 @@
 webpack = require "webpack"
 HtmlWebpackPlugin = require 'html-webpack-plugin'
 version = require("../package.json").version
-path = require('path')

 banner =
   "/**\n" +