Implement populating data file section

Implement populating data file section

Implement populating data file section from existing data

--- js/upload_form.coffee
+++ js/upload_form.coffee
@@ -23,7 +23,6 @@
     memory_usage:memory_usage(data)
   }

-
 set_value = (item) ->
   $('#' + item[0]).attr('value', item[1])

@@ -32,6 +31,158 @@

 memory_usage = (data) ->
   data.data.filter((d) -> d.name == 'memory_usage')[0].values[0].value
+
+
+data_file_html = () ->
+  """{% include data_input.html %}"""
+
+media_file_html = () ->
+  """{% include media_input.html %}"""
+
+add_data_file_section = () ->
+  counter = $('#data-files').children().size() + 2
+  $('#data-files').append(
+    Handlebars.compile(data_file_html())(
+      {
+        counter:counter
+        fields:[['x', '',       'required', ''],
+                ['y', '',       'required', ''],
+                ['z', 'hidden', '',         'disabled']]
+      }
+    )
+  )
+  counter
+
+$("#data-add").click(add_data_file_section)
+#   () ->
+#     $('#data-files').append(
+#       Handlebars.compile(data_file_html())(
+#         {
+#           counter:$('#data-files').children().size() + 2
+#           fields:[['x', '',       'required', ''],
+#                   ['y', '',       'required', ''],
+#                   ['z', 'hidden', '',         'disabled']]
+#         }
+#       )
+#     )
+# )
+
+$("#media-add").click(
+  () ->
+    $('#media-files').append(
+      Handlebars.compile(media_file_html())(
+        {
+          counter:$('#media-files').children().size() + 10
+        }
+      )
+    )
+)
+
+
+$("#data-files").on('click', '.data-remove',
+  () ->
+     $("#data-block-" + this.id.split('-')[2]).remove()
+)
+
+$("#media-files").on('click', '.media-remove',
+  () ->
+     $("#media-block-" + this.id.split('-')[2]).remove()
+)
+
+parse_field_ = (counter, field) ->
+  f = (tag) ->
+    $(tag).attr(
+      'name'
+      $(tag).attr('name') + '[' + $(tag).val() + ']'
+    )
+    $(tag).val('number')
+  f('#data-' + field + '-parse-' + counter)
+
+expr_field_ = (counter, field) ->
+  f = (expr_tag, data_tag) ->
+    $(expr_tag).val(
+      $(expr_tag).val() + $(data_tag).val()
+    )
+  f('#expr-' + field + '-' + counter, '#data-' + field + '-parse-' + counter)
+
+field_ = (func) ->
+  (field) ->
+    map(
+      (x) ->
+        func(x, field)
+      map((x) ->
+            x.id.split('-')[2]
+          $('#data-files').children())
+    )
+
+$('#my_form').submit(
+  () ->
+    map(
+      (x) ->
+        field_(expr_field_)(x)
+        field_(parse_field_)(x)
+      ['x', 'y', 'z']
+    )
+)
+
+get_tags = (thiss) ->
+  f = (x) ->
+    ['#input-field-z-' + x,
+     '#data-z-parse-' + x,
+     '.field-input-z-' + x]
+  f(thiss.id.split('-')[2])
+
+
+$('#data-files').on('click', '.dim-line',
+  () ->
+    [div_tag, input_tag, field_class] = get_tags(this)
+    $(div_tag).attr('hidden', '')
+    $(input_tag).removeAttr('required')
+    $(field_class).attr('disabled', '')
+)
+
+add_contour = (thiss) ->
+  [div_tag, input_tag, field_class] = get_tags(thiss)
+  $(div_tag).removeAttr('hidden')
+  $(input_tag).attr('required', '')
+  $(field_class).removeAttr('disabled')
+
+$('#data-files').on('click', '.dim-contour',
+  () ->
+    add_contour(this)
+)
+
+
+get_field_name = (datum, field) ->
+  if datum.transform?
+    datum.transform.filter((x) -> x.as == field)[0].expr.split('.')[1]
+  else
+    field
+
+populate_datum = (datum) ->
+  counter = add_data_file_section()
+  $('#data-name-' + counter).val(datum.name)
+  $('#data-url-' + counter).val(datum.url)
+  $('#data-desc-' + counter).val(datum.description)
+  if datum.format? and datum.format.type == 'json'
+    $('#json-' + counter).attr('checked', '')
+    $('#csv-' + counter).removeAttr('checked')
+  $('#data-x-parse-' + counter).val(get_field_name(datum, 'x'))
+  $('#data-y-parse-' + counter).val(get_field_name(datum, 'y'))
+  if datum.type == 'contour'
+    add_contour($('#dim-contour-' + counter)[0])
+    $('#data-z-parse-' + counter).val(get_field_name(datum, 'z'))
+    $('#dim-contour-' + counter).attr('checked', '')
+    $('#line-contour-' + counter).removeAttr('checked')
+
+
+populate_data_section = (data) ->
+  map(
+    populate_datum
+    data.data.filter(
+      (d) -> (d.type == 'contour' or d.type == 'line') and d.url?
+    )
+  )

 SIM_NAME = new URL(window.location.href).searchParams.get("sim")

@@ -46,105 +197,4 @@
   $('#arch_' + DATA.metadata.hardware.cpu_architecture).attr('selected', '')
   $('#acc_' + DATA.metadata.hardware.acc_architecture).attr('selected', '')
   $('#par_' + DATA.metadata.hardware.parallel_model).attr('selected', '')
-
-data_file_html = () ->
-  """{% include data_input.html %}"""
-
-media_file_html = () ->
-  """{% include media_input.html %}"""
-
-$("#data-add").click(
-  () ->
-    $('#data-files').append(
-      Handlebars.compile(data_file_html())(
-        {
-          counter:$('#data-files').children().size() + 2
-          fields:[['x', '',       'required', ''],
-                  ['y', '',       'required', ''],
-                  ['z', 'hidden', '',         'disabled']]
-        }
-      )
-    )
-)
-
-$("#media-add").click(
-  () ->
-    $('#media-files').append(
-      Handlebars.compile(media_file_html())(
-        {
-          counter:$('#media-files').children().size() + 10
-        }
-      )
-    )
-)
-
-
-$("#data-files").on('click', '.data-remove',
-  () ->
-     $("#data-block-" + this.id.split('-')[2]).remove()
-)
-
-$("#media-files").on('click', '.media-remove',
-  () ->
-     $("#media-block-" + this.id.split('-')[2]).remove()
-)
-
-parse_field_ = (counter, field) ->
-  f = (tag) ->
-    $(tag).attr(
-      'name'
-      $(tag).attr('name') + '[' + $(tag).val() + ']'
-    )
-    $(tag).val('number')
-  f('#data-' + field + '-parse-' + counter)
-
-expr_field_ = (counter, field) ->
-  f = (expr_tag, data_tag) ->
-    $(expr_tag).val(
-      $(expr_tag).val() + $(data_tag).val()
-    )
-  f('#expr-' + field + '-' + counter, '#data-' + field + '-parse-' + counter)
-
-field_ = (func) ->
-  (field) ->
-    map(
-      (x) ->
-        func(x, field)
-      map((x) ->
-            x.id.split('-')[2]
-          $('#data-files').children())
-    )
-
-$('#my_form').submit(
-  () ->
-    map(
-      (x) ->
-        field_(expr_field_)(x)
-        field_(parse_field_)(x)
-      ['x', 'y', 'z']
-    )
-)
-
-get_tags = (thiss) ->
-  f = (x) ->
-    ['#input-field-z-' + x,
-     '#data-z-parse-' + x,
-     '.field-input-z-' + x]
-  f(thiss.id.split('-')[2])
-
-
-$('#data-files').on('click', '.dim-line',
-  () ->
-    [div_tag, input_tag, field_class] = get_tags(this)
-    $(div_tag).attr('hidden', '')
-    $(input_tag).removeAttr('required')
-    $(field_class).attr('disabled', '')
-)
-
-$('#data-files').on('click', '.dim-contour',
-  () ->
-    [div_tag, input_tag, field_class] = get_tags(this)
-    $(div_tag).removeAttr('hidden')
-    $(input_tag).attr('required', '')
-    $(field_class).removeAttr('disabled')
-)
+  populate_data_section(DATA)


fix up bucket modal to work with new models and collections

--- src/node_modules/bucket-modal/bucket-modal-controller.coffee
+++ src/node_modules/bucket-modal/bucket-modal-controller.coffee
@@ -1,9 +1,9 @@
 _ = require('lodash')

 ### @ngInject ###
-module.exports = ($scope, $modalInstance, BucketsStore, BucketModel, AuthService, group, round, bucket) ->
+module.exports = ($scope, $modalInstance, BucketsStore, BucketModel, AuthService, UserModel, group, round, bucket) ->

-  currentUser = AuthService.getCurrentUser()
+  currentUser = new UserModel(AuthService.getCurrentUser())

   if group.isAdmin(currentUser)
     $scope.sponsors = group.members
@@ -37,7 +37,10 @@
     if bucketForm.$invalid
       return

-    unsavedBucket = new BucketModel($scope.data)
+    data = $scope.data
+    data.user = data.user.toJSON()
+
+    unsavedBucket = new BucketModel(data)

     BucketsStore.save(unsavedBucket)
     .then (savedBucket) ->


Add return statement.

Add return statement.

--- app/assets/volume/slot.coffee
+++ app/assets/volume/slot.coffee
@@ -730,6 +730,9 @@
                   body: constants.message('asset.update.error', @name)
                   report: res
                   owner: this
+        else
+          return
+

       canRestore: () ->
         uploads.removedAsset? if editing && this == blank && uploads.removedAsset?.volume.id == slot.volume.id


don't modify expiry for temporary packs

don't modify expiry for temporary packs

--- app/coffee/PackManager.coffee
+++ app/coffee/PackManager.coffee
@@ -224,8 +224,8 @@
 			return callback(err) if err?
 			if not pack?
 				MongoAWS.unArchivePack project_id, doc_id, pack_id, callback
-			else if pack.expiresAt? and not pack.temporary and false # TODO: remove false, temporarily disabled
-				# we only need to touch the TTL on the listing of changes in the project
+			else if pack.expiresAt? and pack.temporary is false
+				# we only need to touch the TTL when listing the changes in the project
 				# because diffs on individual documents are always done after that
 				PackManager.increaseTTL pack, callback
 				# only do this for cached packs, not temporary ones to avoid older packs


Update publishing.iced

Update publishing.iced

--- .gulp/publishing.iced
+++ .gulp/publishing.iced
@@ -10,10 +10,8 @@
   # publish core package
   await execute "npm publish --tag preview",{cwd:package_folder, silent:false }, defer c,o,e
   echo  "\n\nPublished Core:  #{package_json.name}@#{info package_json.version} (tagged as @preview)\n\n"
-  echo stdout:
-  echo o
-  echo stderr:
-  echo e
+  echo "stdout:\n #o"
+  echo "stderr:\n #e"

   # update bootstrapper package.json
@@ -25,4 +23,7 @@

   await execute "npm publish --tag preview",{cwd:package_folder, silent:false }, defer c,o,e
   echo  "\n\nPublished Bootstrapper:  #{package_json.name}@#{info package_json.version} (tagged as @preview)\n\n"
+  echo "stdout:\n #o"
+  echo "stderr:\n #e"
+
   done()


fix #43

fix #43

--- app/js/services/wallet.coffee
+++ app/js/services/wallet.coffee
@@ -5,7 +5,8 @@
     approvals: {}

     balances: {}
-    bonuses: {}
+    # bonuses: {}
+    vesting_balances: {}

     asset_balances : {}

@@ -47,7 +48,8 @@
         clear @contacts
         clear @approvals
         clear @balances
-        clear @bonuses
+        # clear @bonuses
+        clear @vesting_balances
         clear @asset_balances
         clear @transactions
         @transactions["*"]=[]
@@ -104,8 +106,9 @@
         @blockchain.refresh_asset_records().then =>
             @main_asset = @blockchain.asset_records[0]
             requests =
-                refresh_bonuses: @refresh_bonuses()
+                # refresh_bonuses: @refresh_bonuses()
                 account_balances : @wallet_api.account_balance("")
+                refresh_vesting_balances: @refresh_vesting_balances("")
             @q.all(requests).then (results) =>
                 for name_bal_pair in results.account_balances
                     name = name_bal_pair[0]
@@ -132,24 +135,50 @@

         return @refresh_balances_promise

-    refresh_bonuses_promise: null
-
-    refresh_bonuses: ->
-        if @utils.too_soon("refresh_bonuses", 10 * 1000)
-            return @refresh_bonuses_promise.then (response) =>
-                #console.log "wallet_account_yield(): too soon #{response}"
-                return response
-
-        @refresh_bonuses_promise = @wallet_api.account_yield("").then (response) =>
-            for name_balances_pair in response
-                name = name_balances_pair[0]
-                for asset_id_amt_pair in name_balances_pair[1]
-                    asset_id = asset_id_amt_pair[0]
-                    symbol = @blockchain.asset_records[asset_id].symbol
-                    amount = asset_id_amt_pair[1]
-                    @bonuses[name] = @bonuses[name] || {}
-                    @bonuses[name][symbol] = @utils.newAsset(amount, symbol, @blockchain.symbol2records[symbol].precision)
-
+    # refresh_bonuses_promise: null
+
+    # refresh_bonuses: ->
+    #     if @utils.too_soon("refresh_bonuses", 10 * 1000)
+    #         return @refresh_bonuses_promise.then (response) =>
+    #             #console.log "wallet_account_yield(): too soon #{response}"
+    #             return response
+    #
+    #     @refresh_bonuses_promise = @wallet_api.account_yield("").then (response) =>
+    #         for name_balances_pair in response
+    #             name = name_balances_pair[0]
+    #             for asset_id_amt_pair in name_balances_pair[1]
+    #                 asset_id = asset_id_amt_pair[0]
+    #                 symbol = @blockchain.asset_records[asset_id].symbol
+    #                 amount = asset_id_amt_pair[1]
+    #                 @bonuses[name] = @bonuses[name] || {}
+    #                 @bonuses[name][symbol] = @utils.newAsset(amount, symbol, @blockchain.symbol2records[symbol].precision)
+
+    refresh_vesting_balances_promise: null
+    refresh_vesting_balances: =>
+        @refresh_vesting_balances_promise = @wallet_api.account_vesting_balances("").then (response) =>
+          for name_balanes_pair in response
+             name = name_balanes_pair[0]
+             @vesting_balances[name] = name_balanes_pair[1]
+
+    vesting_balances_summary: (name) =>
+        return @vesting_balances_summary[name] if @vesting_balances_summary[name]
+        return 0 unless @vesting_balances[name]
+
+        available = 0; vested = 0; claimed = 0; original = 0
+        for record in @vesting_balances[name]
+            available += record["available_balance"]
+            vested += record["vested_balance"]
+            claimed += record["claimed_balance"]
+            original += record["original_balance"]
+
+        symbol = 'PLS'; precision = @blockchain.symbol2records[symbol].precision
+        return (
+            @vesting_balances_summary[name] =
+                available: @utils.newAsset available, symbol, precision
+                vested:    @utils.newAsset vested, symbol, precision
+                claimed:   @utils.newAsset claimed, symbol, precision
+                original:  @utils.newAsset original, symbol, precision
+        )

     # turn raw rpc return value into nice object
     populate_account: (val) ->


Minor fix

Minor fix

--- app/modules/host/index.coffee
+++ app/modules/host/index.coffee
@@ -319,7 +319,7 @@
       }

       params = {
-        host: $scope.host.$pool.id
+        pool: $scope.host.$pool
         name,
       }


Use password reset request function from auth module

--- app/pages/reset-password.cjsx
+++ app/pages/reset-password.cjsx
@@ -1,4 +1,5 @@
 React = require 'react'
+auth = require '../api/auth'
 apiClient = require '../api/client'

 RequestForm = React.createClass
@@ -40,7 +41,15 @@

So, you’ve forgotten your password.

It happens to the best of us. Just enter your email address here and we’ll send you a link you can follow to reset it.

<input ref="email" type="email" className="standard-input" defaultValue={@props.query?.email} size="50" />

-
<button type="submit" className="standard-button">Submit</button>

+

+            <button type="submit" className="standard-button">Submit</button>{' '}
+            {if @state.inProgress
+
+            else if @state.emailSuccess
+
+            else if @state.emailError?
+              {@state.emailError.toString()}}
+

         </form>}

@@ -74,11 +83,7 @@
       emailSuccess: false
       emailError: null

-    payload =
-      users:
-        email: @refs.email.getDOMNode().value
-
-    apiClient.post '../users/password', payload
+    auth.requestPasswordReset email: @refs.email.getDOMNode().value
       .then =>
         @setState emailSuccess: true
       .catch (error) =>


Remove unused query for users

Remove unused query for users

--- apps/organizations/routes.coffee
+++ apps/organizations/routes.coffee
@@ -30,7 +30,6 @@
     res.render "#{__dirname}/views/dashboard",
       org: req.org
       badges: req.org.badges(10)
-      users: req.org.users()
       badgeCount: req.org.badgeCount()

   app.get '/users', authenticate, (req, res, next) ->


Only check for buggy IndexedDB once

Only check for buggy IndexedDB once

--- assets/javascripts/app/db.coffee
+++ assets/javascripts/app/db.coffee
@@ -23,7 +23,9 @@
   onOpenSuccess: (event) =>
     try
       db = event.target.result
-      db.transaction(['docs', app.docs.all()[0].slug], 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
+      unless @checkedBuggyIDB
+        db.transaction(['docs', app.docs.all()[0].slug], 'readwrite').abort() # https://bugs.webkit.org/show_bug.cgi?id=136937
+        @checkedBuggyIDB = true
     catch
       try db.close()
       @onOpenError()


Refactor index.recent and index.my_repositories routes

--- assets/scripts/app/routes.coffee
+++ assets/scripts/app/routes.coffee
@@ -152,58 +152,39 @@
     existingUser = document.location.hash.match(/#existing[_-]user/)
     controller.set('existingUser', existingUser)

-Travis.IndexMyRepositoriesRoute = Travis.Route.extend
+Travis.IndexTabRoute = Travis.Route.extend
   renderTemplate: ->
     @render 'repo'
     @render 'build', into: 'repo'

   setupController: ->
     @_super.apply this, arguments
+
+    @controllerFor('repo').activate('index')
+    @controllerFor('repos').activate(@get('reposTabName'))
+
     @currentRepoDidChange()
-
-    @controllerFor('repo').activate('index')
-    @controllerFor('repos').activate('owned')
     @controllerFor('repos').addObserver('firstObject', this, 'currentRepoDidChange')

-  afterModel: ->
-    @controllerFor('repos').possiblyRedirectToGettingStartedPage()

   deactivate: ->
     @controllerFor('repos').removeObserver('firstObject', this, 'currentRepoDidChange')

   currentRepoDidChange: ->
-    @controllerFor('repo').set('repo', @controllerFor('repos').get('firstObject'))
+    if repo = @controllerFor('repos').get('firstObject')
+      @controllerFor('repo').set('repo', repo)

   actions:
     redirectToGettingStarted: ->
       @transitionTo('getting_started')

-
-Travis.IndexRecentRoute = Travis.Route.extend
-  renderTemplate: ->
-    @render 'repo'
-    @render 'build', into: 'repo'
-
-  setupController: ->
-    @_super.apply this, arguments
-    @currentRepoDidChange()
-
-    @controllerFor('repo').activate('index')
-    @controllerFor('repos').activate('recent')
-    @controllerFor('repos').addObserver('firstObject', this, 'currentRepoDidChange')
-
+Travis.IndexMyRepositoriesRoute = Travis.IndexTabRoute.extend
+  reposTabName: 'owned'
   afterModel: ->
     @controllerFor('repos').possiblyRedirectToGettingStartedPage()

-  deactivate: ->
-    @controllerFor('repos').removeObserver('firstObject', this, 'currentRepoDidChange')
-
-  currentRepoDidChange: ->
-    @controllerFor('repo').set('repo', @controllerFor('repos').get('firstObject'))
-
-  actions:
-    redirectToGettingStarted: ->
-      @transitionTo('getting_started')
+Travis.IndexRecentRoute = Travis.IndexTabRoute.extend
+  reposTabName: 'recent'

 Travis.AbstractBuildsRoute = Travis.Route.extend
   renderTemplate: ->


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -283,9 +283,9 @@
             .duration(1500)
             #.attrTween("d", pieTween)
             .attrTween("d", (d,i,a) ->
-                i = d3.interpolate({startAngle: 0, endAngle: 0}, {startAngle: d.startAngle, endAngle: d.endAngle})
-                return t ->
-                    b = i(t)
+                x = d3.interpolate({startAngle: 0, endAngle: 0}, {startAngle: d.startAngle, endAngle: d.endAngle})
+                return (t) ->
+                    b = x(t)
                     return arc(b)
             )


Fix total time output

Fix total time output

--- console/runner.coffee
+++ console/runner.coffee
@@ -51,7 +51,7 @@

     arr = (name: k, total: total_timings[k], self: v, counts:call_counts[k] for k, v of self_timings)
     arr.sort (a, b) -> b.self - a.self
-    total_time = total_timings["#{cname}::main([Ljava/lang/String;)"]
+    total_time = total_timings["L#{cname};::main([Ljava/lang/String;)V"]

     console.log "\nProfiler results: #{total_time} ms total"
     console.log ['total','self','calls','self ms/call','name'].join '\t'


Agent pie: pointer stroke width

Agent pie: pointer stroke width

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -311,7 +311,7 @@
             .attr('class', 'pointer')
             .style('fill', 'none')
             .style('stroke', 'black')
-            .attr('stroke-width', 2)
+            .attr('stroke-width', 1.2)
             .attr('marker-end', 'url(#circ)')
             .style('opacity', 0)
         pointers.exit().remove()


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -103,6 +103,8 @@
     #console.log("path",this.path.empty())
     path.enter().append('path').attr('class', 'pie').attr 'fill', (d, i) ->
       color i
+    path.attr('d',arc)
+        .exit()
     #@path.transition().duration(1500).attrTween 'd', that.pieTween
     #path.transition()
     #    .duration(1000)


Changes the interval images stay up to 10 seconds

--- widgets/imagecarousel/imagecarousel.coffee
+++ widgets/imagecarousel/imagecarousel.coffee
@@ -10,7 +10,7 @@
     @currentIndex = Math.max(0, @get('urls').indexOf(@get('current_url')))

   startCarousel: ->
-    setInterval(@nextImage, 7000)
+    setInterval(@nextImage, 10000)

   nextImage: =>
     urls = @get('urls')


Use .each

Use .each

--- workers/social/lib/social/models/vm.coffee
+++ workers/social/lib/social/models/vm.coffee
@@ -97,24 +97,23 @@
     JDomain = require './domain'
     JUser   = require './user'

-    JVM.all {}, (err, vms)=>
+    JVM.each {}, {}, (err, vm)=>
       return callback err  if err
-      return callback null, null  unless vms
-      vms.forEach (vm)=>
-        {nickname, groupSlug, uid, type} = @parseAlias vm.hostnameAlias
-        hostnameAliases = JVM.createAliases {
-          nickname, type, uid, groupSlug
-        }
-        vmUser = vm.users.filter (u)->
-          return u.owner is yes
-        if vmUser.length > 0
-          JUser.one
-            _id: vmUser[0].id
-          , (err, user)=>
-            if not err and user
-              user.fetchAccount 'koding', (err, account)=>
-                if not err and account
-                  @createDomains account, hostnameAliases, hostnameAliases[0]
+      return callback null, null  unless vm
+      {nickname, groupSlug, uid, type} = @parseAlias vm.hostnameAlias
+      hostnameAliases = JVM.createAliases {
+        nickname, type, uid, groupSlug
+      }
+      vmUser = vm.users.filter (u)->
+        return u.owner is yes
+      if vmUser.length > 0
+        JUser.one
+          _id: vmUser[0].id
+        , (err, user)=>
+          if not err and user
+            user.fetchAccount 'koding', (err, account)=>
+              if not err and account
+                @createDomains account, hostnameAliases, hostnameAliases[0]

   @ensureDomainSettings = ({account, vm, type, nickname, groupSlug})->
     domain = 'kd.io'


Remove storage.local

Remove storage.local

--- app/src/utils/storage/storage.coffee
+++ app/src/utils/storage/storage.coffee
@@ -2,14 +2,11 @@

 @ledger.storage.openStores = (bitIdAddress, passphrase) ->
   localStorage = new ledger.storage.SecureStore 'ledger.local.' + bitIdAddress, passphrase
-  ledger.storage.local =  new ledger.storage.ObjectStore localStorage
   ledger.storage.sync = new ledger.storage.SyncedStore('ledger.meta.' + bitIdAddress, bitIdAddress, passphrase)
   ledger.storage.wallet = new ledger.storage.SecureStore 'ledger.wallet.' + bitIdAddress, passphrase
   ledger.storage.databases = new ledger.storage.SecureStore 'ledger.database.' + bitIdAddress, passphrase

 @ledger.storage.closeStores = () ->
-  ledger.storage.local = null
   ledger.storage.sync = null
   ledger.storage.wallet = null
-
-
+  ledger.storage.databases = null


Adds back missing test

Adds back missing test

--- test/unit/transaction-runner-test.coffee
+++ test/unit/transaction-runner-test.coffee
@@ -56,6 +56,9 @@

     it 'should add advice', () ->
       assert.ok advisableStub.async.call.called
+
+    it 'should add hooks', () ->
+      assert.ok addHooksStub.called

   describe 'configureTransaction(transaction, callback)', () ->


app/storage: expose ready state

app/storage: expose ready state

--- client/app/lib/appstorage.coffee
+++ client/app/lib/appstorage.coffee
@@ -13,6 +13,8 @@

     @_applicationID      = appId
     @_applicationVersion = version
+
+    @isReady = no

     @reset()

@@ -33,8 +35,7 @@
           if not error and storage
             @_storage = storage
             callback? @_storage
-            @emit 'storageFetched'
-            @emit 'ready'
+            @_setReady()
           else
             callback? null

@@ -42,8 +43,17 @@

       kd.utils.defer =>
         callback? @_storage
-        @emit 'storageFetched'
-        @emit 'ready'
+        @_setReady()
+
+
+  _setReady: ->
+
+    @isReady = yes
+
+    @emit 'storageFetched' # this shouldn't be here, not sure what else is using this.
+                           # most probably obsolete. -og
+
+    @emit 'ready'

   fetchValue: (key, callback, group = DEFAULT_GROUP_NAME, force = no) ->
@@ -59,14 +69,14 @@

     return unless @_storage
     return if @_storageData[group]?[key]? then @_storageData[group][key]
-    return if @_storage[group]?[key]? then @_storage[group][key]
+    return if @_storage[group]?[key]?     then @_storage[group][key]

   setValue: (key, value, callback, group = DEFAULT_GROUP_NAME) ->

     pack = @zip key, group, value

-    @_storageData[group] = {}  unless @_storageData[group]?
+    @_storageData[group]      = {}  unless @_storageData[group]?
     @_storageData[group][key] = value

     @fetchStorage (storage) ->
@@ -94,14 +104,14 @@

   reset: ->

-    @_storage = null
+    @_storage     = null
     @_storageData = {}

   zip: (key, group, value) ->

-    pack = {}
-    _key = group+'.'+key
+    pack       = {}
+    _key       = group+'.'+key
     pack[_key] = value

     pack


record screen height in mixpanel

record screen height in mixpanel

--- js/outer/home.coffee
+++ js/outer/home.coffee
@@ -1,7 +1,9 @@
 class CI.outer.Home extends CI.outer.Page
   lib: () =>
     _gaq.push(['_trackPageview', '/homepage'])
-    mixpanel.track("Outer Home Page")
+    mixpanel.track("Outer Home Page", {
+      'screen height': $( window ).height();
+      })

   viewContext: =>
     features: [


:boom::worried: Updated at https://danielx.net/editor/

--- player.coffee
+++ player.coffee
@@ -139,6 +139,10 @@

     loadFromURL: self.loadFromURL

+  postmaster.invokeRemote "ready"
+  .catch (e) ->
+    console.warn e.message
+
   return self

 animate = (fn) ->


Better doc comments.

Better doc comments.

--- lib/machine.coffee
+++ lib/machine.coffee
@@ -37,6 +37,18 @@
 		return callback null, parse.property_list(output) if callback

 ###
+	* Removes vm. The vm files are automatically deleted.
+	*
+	* @param {string} vm
+	* @param {function(?err)} callback
+###
+exports.remove = (vm, callback) ->
+	command.exec 'unregistervm', vm, '--delete', (err, code, output) ->
+		return callback err if err
+		return callback new Error "cannot remove #{vm}" if code > 0
+		return do callback if callback
+
+###
 	* Imports vm.
 	*
 	* @param {string} path
@@ -65,24 +77,12 @@
 ###
 	* Clones vm. The vm is automatically registered.
 	*
-	* @param {string} from
-	* @param {string} to
+	* @param {string} src_vm
+	* @param {string} to_vm
 	* @param {function(?err)} callback
 ###
-exports.clone = (from, to, callback) ->
-	command.exec 'clonevm', from, '--name', to, '--register', (err, code, output) ->
+exports.clone = (src_vm, to_vm, callback) ->
+	command.exec 'clonevm', src_vm, '--name', to_vm, '--register', (err, code, output) ->
 		return callback err if err
-		return callback new Error "cannot clone #{from} into #{to}" if code > 0
+		return callback new Error "cannot clone #{src_vm} into #{to_vm}" if code > 0
 		return do callback if callback
-
-###
-	* Removes vm. The vm files are deleted.
-	*
-	* @param {string} vm
-	* @param {function(?err)} callback
-###
-exports.remove = (vm, callback) ->
-	command.exec 'unregistervm', vm, (err, code, output) ->
-		return callback err if err
-		return callback new Error "cannot remove #{vm}" if code > 0
-		return do callback if callback


Add env to logging

Add env to logging

--- lib/metrics.coffee
+++ lib/metrics.coffee
@@ -1,13 +1,15 @@
 _ = require 'underscore'
 kayvee = require 'kayvee'
+
+env = process.env.ENV or 'staging'

 # log_memory_usage logs HeapUsed, HeapTotal, and RSS in the kayvee format
 log_memory_usage = (source) ->
     mem = process.memoryUsage()
-    console.error kayvee.formatLog(source, kayvee.INFO, 'HeapUsed', {type: "gauge", value: mem.heapUsed})
-    console.error kayvee.formatLog(source, kayvee.INFO, 'HeapTotal', {type: "gauge", value: mem.heapTotal})
-    console.error kayvee.formatLog(source, kayvee.INFO, 'RSS', {type: "gauge", value: mem.rss})
-
+    type = "gauge"
+    console.error kayvee.formatLog source, kayvee.INFO, 'HeapUsed', {type, env, value: mem.heapUsed}
+    console.error kayvee.formatLog source, kayvee.INFO, 'HeapTotal', {type, env, value: mem.heapTotal}
+    console.error kayvee.formatLog source, kayvee.INFO, 'RSS', {type, env, value: mem.rss}

 # Exposing last period ms to make testing easier. It means a global variable, which isn't ideal, but I
 # think it makes the code cleaner in this case, and since this module is small it's not a big concern
@@ -31,7 +33,9 @@

     # If the pause is long enough log it immediately so we can potentially associate it with an api request
     if pause_ms > pause_threshold_ms
-      console.error kayvee.formatLog(source, kayvee.INFO, 'Pause Detected', { pause_duration : pause_ms})
+      console.error kayvee.formatLog source, kayvee.INFO, 'Pause Detected',
+        pause_duration: pause_ms
+        env: env

     # Update the variables for the next call
     module.exports._last_period_pause_ms += pause_ms
@@ -40,7 +44,10 @@
   setInterval pause_fn, sleep_time_ms

 log_pauses = (source) ->
-  console.error kayvee.formatLog(source, kayvee.INFO, 'PauseMetric', { type: "gauge", value : module.exports._last_period_pause_ms})
+  console.error kayvee.formatLog source, kayvee.INFO, 'PauseMetric',
+    type: "gauge"
+    value: module.exports._last_period_pause_ms
+    env: env
   module.exports._last_period_pause_ms = 0


Fixes tests

Fixes tests

Seems like we receive the pane `destroyed` event several time when
running test, raising an exception when trying to destroy an already
removed view.

--- lib/minimap.coffee
+++ lib/minimap.coffee
@@ -36,5 +36,5 @@
       @minimapViews[paneView.model.id] = view

       paneView.model.on 'destroyed', =>
-        @minimapViews[paneView.model.id].destroy()
+        @minimapViews[paneView.model.id]?.destroy()
         delete @minimapViews[paneView.model.id]


remove todo message (msg taken care of)

remove todo message (msg taken care of)

--- lib/payload.coffee
+++ lib/payload.coffee
@@ -47,7 +47,7 @@
         request:
           method: req.method.toUpperCase()
           'content-type': req.headers['content-type']
-    session: # TODO: figure out why these aren't populating
+    session:
       api_key: req.headers['x-cloudmine-apikey'] or req.query.apikey
       app_id: req.params.appid
       session_token: req.headers['x-cloudmine-sessiontoken'] or null


factor out collapsible part of result view

--- lib/results.coffee
+++ lib/results.coffee
@@ -1,4 +1,7 @@
 # TODO: esc key to remove current result
+# In general this is weird and needs a refactor
+
+tree = require './tree'

 module.exports =
   timeout: (t, f) -> setTimeout f, t
@@ -13,29 +16,29 @@
     body.classList.add 'body'
     body

+  collapsible: (opts) ->
+    view = document.createElement 'div'
+    header = @header()
+    body = @body()
+    view.appendChild header
+    view.appendChild body
+    header.innerText = opts.header
+    body.innerText = opts.body
+    view
+
   result: (ed, opts) ->
     view = document.createElement 'div'
     view.classList.add 'ink', 'inline', 'result'
     view.style.position = 'relative'
     view.style.top = -ed.getLineHeightInPixels() + 'px'
     view.style.left = '10px'
-    header = @header()
-    body = @body()
-    view.appendChild header
-    view.appendChild body
-    header.innerText = opts.header
-    body.innerText = opts.body
+    view.appendChild @collapsible opts
     view: view
-    header: header
-    body: body

   methods: (r) ->
     r.destroy = => @remove r
     r.invalidate = => @invalidate r
     r.validate = => @validate r
-    r.show = => @showBody r
-    r.hide = => @hideBody r
-    r.toggle = => @toggle r

   show: (ed, mark, {watch, header, body}={}) ->
     mark.getBufferRange().isReversed and throw "Cannot add result to reversed marker"
@@ -113,17 +116,6 @@
       if old.isLessThan(nu) && text.match /^\r?\n\s*$/
         r.marker.setHeadBufferPosition old

-  showBody: (r) ->
-    r.body.style.display = null
-    r.hidden = false
-
-  hideBody: (r) ->
-    r.body.style.display = 'none'
-    r.hidden = true
-
-  toggle: (r) ->
-    if r.hidden then @showBody r else @hideBody r
-
   forLines: (ed, start, end) ->
     ed.findMarkers().filter((m)->m.result? &&
                                  m.getBufferRange().intersectsRowRange(start, end))


Remove console.log

Remove console.log

--- lib/watcher.coffee
+++ lib/watcher.coffee
@@ -125,16 +125,12 @@
       marker

   destroyReferences: ->
-    console.log '  destroyReferences'
-
     return unless @referenceMarkers?
     for marker in @referenceMarkers
       marker.destroy()
     delete @referenceMarkers

   createReferences: ->
-    console.log '  createReferences'
-
     ranges = @ripper.find @editor.getSelectedBufferRange().start
     @referenceMarkers = for range in ranges
       marker = @editor.markBufferRange range


update pattern

update pattern

--- grammars/nsL.cson
+++ grammars/nsL.cson
@@ -36,7 +36,7 @@
     name: "support.class.nsl"
   }
   {
-    match: "^\\s*(?i)(break|case|default|do|else|for|if|return|switch|while)\\b"
+    match: "^\\s*(?i)(break|case|default|do|else|for|if|return|switch|while)(?=\\s*\\()"
     name: "entity.name.section.nsl"
   }
   {


add memorial invitations for 2019 and 2020

--- client/views/pages/store/store.coffee
+++ client/views/pages/store/store.coffee
@@ -145,6 +145,10 @@
 				short: 'jwcd'
 			,
 				short: 'mi18'
+			,
+				short: 'mi19'
+			,
+				short: 'mi20'
 			]
 		]


Add context menu on comment view

Add context menu on comment view

--- src/renderer/scripts/views/main/comment/collectionView.coffee
+++ src/renderer/scripts/views/main/comment/collectionView.coffee
@@ -17,6 +17,13 @@

         app.nsenStream.onDidChangeStream =>
             @_listenLiveEvents()
+
+        app.contextMenu.add "body", [
+             {
+                label   : 'コピー',
+                role    : 'copy'
+            }
+        ]

         # @collection = new Backbone.Collection
         # _.bindAll @


rename Wood Chuck to Woodchuck

rename Wood Chuck to Woodchuck

--- app/translations/en_us.coffee
+++ app/translations/en_us.coffee
@@ -354,7 +354,7 @@
     '''

     woodChuck:
-      label: 'Wood Chuck'
+      label: 'Woodchuck'
       description: '''
         This animal is also known as a groundhog. It has a brown furry coat, clawed feets, small eyes and ears, and a short, flat tail.
     '''


fix: UV coords finally work!

fix: UV coords finally work!

--- 3d/singlerot3d.coffee
+++ 3d/singlerot3d.coffee
@@ -252,12 +252,6 @@
       w* 0.5, h*-0.5, z,
       w*-0.5, h* 0.5, z,
       w* 0.5, h* 0.5, z]
-  uvs = new Float32Array [
-    0, 0,
-    w, 0
-    0, h
-    w, h
-  ]
   # 2 3
   # 0 1
   ixs = new Uint16Array [
@@ -265,6 +259,11 @@
     1, 3, 2
     ]

+  uvs = new Float32Array [
+    0, 0,   1, 0,   0, 1  #0 1 2
+    1, 0,   1, 1,   0, 1  #1 3 2
+  ]
+
   plane = new THREE.BufferGeometry()
   plane.addAttribute 'position', new THREE.BufferAttribute(vs, 3)
   plane.addAttribute 'index', new THREE.BufferAttribute(ixs, 1)
@@ -277,7 +276,7 @@

   material = new THREE.MeshBasicMaterial
     map: texture
-    color: 0x00FF00
+    #color: 0x00FF00
     side: THREE.DoubleSide

   planeMesh = new THREE.Mesh plane, material


components: DBusLoader: code cleanup

components: DBusLoader: code cleanup

--- components/DbusComponentLoader.coffee
+++ components/DbusComponentLoader.coffee
@@ -2,17 +2,6 @@
 Gio = imports.gi.Gio
 Runtime = imports.runtime
 Utils = imports.utils
-
-loadInterface = (loader, ifaceInfo) ->
-  log "iface->#{ifaceInfo}"
-  log "iface: #{ifaceInfo.name}"
-
-loadNode = (load, nodeInfo) ->
-
-loadNodes = (loader, fileInfo) ->
-  for node in fileInfo.nodes
-    log node
-    loadInterface loader, iface

 loadInterface = (loader, iface) ->
   log "iface name=#{iface.name}"


fixes for several minor issues with colors when changing background images

--- @client/banner.coffee
+++ @client/banner.coffee
@@ -8,8 +8,8 @@
     subdomain = fetch '/subdomain'
     edit_banner = fetch 'edit_banner'
     title = edit_banner.title or customization('banner')?.title or @props.title
+
     is_admin = fetch('/current_user').is_admin
-    is_light = is_light_background()

     DIV
       className: 'CustomizeTitle'
@@ -26,8 +26,12 @@
             line-height: 1.4;
           }
           .CustomizeTitle > .banner_title::placeholder {
-            color: #{if is_light then 'rgba(0,0,0,.4)' else 'rgb(255,255,255,.6)'};
+            color: rgba(0,0,0,.4);
           }
+          .dark .CustomizeTitle > .banner_title::placeholder, .with-image .CustomizeTitle > .banner_title::placeholder {
+            color: rgb(255,255,255,.6);
+          }
+
         """

       if is_admin && edit_banner.editing
@@ -73,12 +77,17 @@
     if is_admin && edit_banner.editing
       DIV
         id: 'edit_banner'
+        className: 'CustomizeDescription'

         STYLE
           dangerouslySetInnerHTML: __html: """
             #edit_banner .ql-editor {
               min-height: 48px;
             }
+            .wrapper.with-image .CustomizeDescription .ql-editor.ql-blank::before {
+              color: rgba(255,255,255,.4);
+            }
+
           """
         WysiwygEditor
           key: "forum-description"
@@ -482,7 +491,7 @@
         right: 50
         backgroundColor: if is_light then 'rgba(255,255,255,.4)' else 'rgba(0,0,0,.4)'
         padding: '12px 24px'
-        zIndex: 99
+        zIndex: 9

       DIV null,
         DIV
@@ -511,8 +520,6 @@
             style:
               fontSize: 14
               color: color
-              zIndex: 1
-              left: '50%'
               marginBottom: 12
             'Upload background'

@@ -527,7 +534,7 @@
               id: 'background_color'
               type: 'checkbox'
               name: 'background_color'
-              defaultChecked: is_light
+              checked: is_light
               onChange: (e) =>
                 edit_banner.background_css = if e.target.checked then "rgb(255,255,255)" else 'rgb(0,0,0)'
                 save edit_banner
@@ -540,7 +547,7 @@
             htmlFor: "background_color"

             if has_masthead
-              translator("banner.background_css_is_light.label", "Light theme")
+              translator("banner.background_css_is_light.label", "Background is light colored")
             else
               translator("banner.background_css.label", "...or set to color") + ':'

@@ -740,6 +747,7 @@
                     edit_banner.background_css = 'rgb(255,255,255)'
                   else
                     edit_banner.background_css = 'rgb(0,0,0)'
+
                   save edit_banner

                 img.src = fr.result
@@ -963,7 +971,7 @@
           color: white;
           position: relative;
           top: 0;
-        } .dark .PhotoBanner > .wrapper > .text_block {
+        } .dark .PhotoBanner > .wrapper > .text_block, .PhotoBanner > .wrapper.with-image > .text_block {
           color: black;
         }

@@ -1030,7 +1038,7 @@
           key: 'editable_description'
           opts: opts
           style:
-            border: if !has_description then (if is_dark_theme then '1px solid rgba(255,255,255,.5)' else '1px solid rgba(0,0,0,.5)')
+            border: if !has_description then (if has_image_background || is_dark_theme then '1px solid rgba(255,255,255,.5)' else '1px solid rgba(0,0,0,.5)')
             padding: "6px 8px"
             minHeight: 20
             fontSize: 18


Fix JS examples

Fix JS examples

--- bokehjs/src/coffee/api/charts.coffee
+++ bokehjs/src/coffee/api/charts.coffee
@@ -146,6 +146,7 @@

   yaxis = new models.CategoricalAxis()
   ydr = new models.FactorRange({factors: labels})
+  yscale = new models.CategoricalScale()

   if opts.axis_number_format?
     xformatter = new models.NumeralTickFormatter({format: opts.axis_number_format})
@@ -153,6 +154,7 @@
     xformatter = new models.BasicTickFormatter()
   xaxis = new models.LinearAxis({formatter: xformatter})
   xdr = new models.DataRange1d({start: 0})
+  xscale = new models.LinearScale()

   if isArray(opts.palette)
     palette = opts.palette
@@ -237,13 +239,14 @@
   if orientation == "vertical"
     [xdr, ydr] = [ydr, xdr]
     [xaxis, yaxis] = [yaxis, xaxis]
+    [xscale, yscale] = [yscale, xscale]

     for r in renderers
       data = r.data_source.data
       [data.left, data.bottom] = [data.bottom, data.left]
       [data.right, data.top] = [data.top, data.right]

-  plot = new models.Plot({x_range: xdr, y_range: ydr})
+  plot = new models.Plot({x_range: xdr, y_range: ydr, x_scale: xscale, y_scale: yscale})

   if opts.width? then plot.plot_width = opts.width
   if opts.height? then plot.plot_height = opts.height


added version in intro

added version in intro

--- main/intro.coffee
+++ main/intro.coffee
@@ -1,6 +1,8 @@
 ###
+queffee
+- A js dynamic priority work queue

-A js dynamic priority work queue
+version: 1.0RC1

 Copyright (c) 2011 Kailuo Wang


fix for color detector

fix for color detector

Former-commit-id: ac7389e86298365f5f2f252ae8d1a597a25c83e1 [formerly 6a619db8478e7acd003895dfc7265bcb761f5006] [formerly c6d4c73a2ee93b4802fa3c0941f41b49891331d2 [formerly 5344d35eee9fa2d98a7b13ea2ce4155d4380e79f]] [formerly 333a71d4d9e45ece7da8e47b79bc6e9aa1ef78fb [formerly 55de77bf9a7a0222f958cd7173b001c0bf8b0f30] [formerly fff763eac00861181c401f06869cc861db47237c [formerly fff763eac00861181c401f06869cc861db47237c [formerly 10624702cb6eb0c5b2da0fe8cce209067c3f6161]]]]
Former-commit-id: ad1653f3eb1c5add629ef54d420569db944db63b [formerly 9c5bfe5ca2b10e57e654a9e0a2326d949440b411] [formerly 332a44b3785c0389302d490df163cb22f2e716c2 [formerly 671a28f9fb4b49f217c801b61de84c7776c3fd73]]
Former-commit-id: ef3a04d7bfb66a5360dd698b76164d8dd32f69cb [formerly 3a3271674e67365fbe5b950f43b4b157764386cf]
Former-commit-id: 080d314621dfaeab0a0a858ae41f62813fb6a7c0
Former-commit-id: 7d8984eb647b0c1dee79c934193b3f53b3f873e4

--- @client/shared.coffee
+++ @client/shared.coffee
@@ -109,7 +109,7 @@

   while el && el.tagName not in ['BODY', 'HTML']

-    is_image = el.tagName == 'IMG' || el.style['background-image']
+    is_image = el.tagName == 'IMG' || $(el).css('background-image') != 'none'

     # Skip this element if it doesn't contribute to background color
     # or if it is a decendent of behind_el
@@ -117,8 +117,6 @@
     skip_element = (behind_el && $(behind_el).has($(el)).length > 0) ||
                     (!is_image && rgb.a == 0)

-    console.log skip_element, is_image or is_image?, el.style['background-image'], el
-
     if skip_element
       hidden_els.push [el, el.style.visibility]
       el.style.visibility = 'hidden'
@@ -135,7 +133,7 @@
         # we have to extract a background url into a temporary IMG
         # element so that it can be processed by colorThief

-        url = el.style['background-image']
+        url = $(el).css('background-image')
                 .replace(/^url\(["']?/, '').replace(/["']?\)$/, '')
       else
         url = el.src
@@ -158,11 +156,9 @@
             b: rgb[2]
           hsl = rgb_to_hsl rgb
           color = {rgb, hsl}
-          console.log color
           callback color if callback
           return color
         else
-          console.log "timeout"
           setTimeout imagePoll, 50
           return null


屏蔽上传应用

屏蔽上传应用

--- menus/chameleon.cson
+++ menus/chameleon.cson
@@ -53,10 +53,10 @@
             'label':'构建应用',
             'command':'chameleon:bulid-project'
           }
-          {
-            'label':'上传应用',
-            'command':'chameleon:upload-project'
-          }
+          # {
+          #   'label':'上传应用',
+          #   'command':'chameleon:upload-project'
+          # }
         ]
       }
       {


updated subdomain character lengths regex

--- client/app/Applications/Environments.kdapplication/views/domains/domaincreationform.coffee
+++ client/app/Applications/Environments.kdapplication/views/domains/domaincreationform.coffee
@@ -211,7 +211,7 @@
           @showSuccess domain

     else # create a subdomain
-      subDomainPattern = /^[a-zA-Z0-9][a-zA-Z0-9.-]*$/
+      subDomainPattern = /^([a-z0-9]([_\-](?![_\-])|[a-z0-9]){0,60}[a-z0-9]|[a-z0-9])$/
       unless subDomainPattern.test domainName
         createButton.hideLoader()
         return notifyUser "#{domainName} is an invalid subdomain."


update version for plug.dj's return

update version for plug.dj's return

--- core/plugmixer.coffee
+++ core/plugmixer.coffee
@@ -3,8 +3,8 @@

 'use strict'

-VERSION = "2.1.6"
-HTML_VERSION = "2.1.6"
+VERSION = "2.1.7"
+HTML_VERSION = "2.1.7"
 DATE_OF_BIRTH = new Date(2014, 1, 24)

 class Plugmixer
@@ -678,7 +678,7 @@
         .forEach (playlist) -> playlist.updateSyncStatus(syncedPlaylists[playlist.id])

     @add: (plugPlaylistId, ytPlaylistId) ->
-      syncedPlaylists[plugPlaylistId] =
+      syncedPlaylists[plugPlaylistId] =
         youtube: ytPlaylistId
         ignore: []
         lastSynced: null
@@ -696,8 +696,8 @@

     @link: (plugPlaylistId, ytPlaylistId) ->
       if Playlists.getById(plugPlaylistId)?
-        if !syncedPlaylists[plugPlaylistId]?
-          syncedPlaylists[plugPlaylistId] =
+        if !syncedPlaylists[plugPlaylistId]?
+          syncedPlaylists[plugPlaylistId] =
             youtube: ytPlaylistId
             ignore: []
             lastSynced: null
@@ -737,7 +737,7 @@
         ga 'plugmixer.send', 'event', 'sync', 'click', 'login-youtube'

     handleAuthResult = (authResult) ->
-      if authResult and not authResult.error
+      if authResult and not authResult.error
         gapi.client.load 'youtube', 'v3', -> readPlaylists()
       else
         $('#plugmixer-youtube-login').click (event) -> checkAuth false
@@ -809,7 +809,7 @@
           fields: 'items(id,snippet/publishedAt,snippet/resourceId),nextPageToken'
         request.execute (response) ->
           if !response.result? then return console.debug response
-          response.result.items.forEach (item) ->
+          response.result.items.forEach (item) ->
             if item.snippet.resourceId.kind == 'youtube#video'
               videoId = item.snippet.resourceId.videoId
               youtubePlaylistItems[videoId] =
@@ -820,7 +820,7 @@
           else
             process()
             runSync()
-
+
       process = =>
         videoIds = Object.keys(youtubePlaylistItems)
         media = media.filter (m) ->
@@ -836,7 +836,7 @@
       runSync = =>
         remainingCount++
         $("#plugmixer-playlist-#{plugPlaylistId}")
-          .children('.plugmixer-playlist-syncinfo').text "#{remainingCount}/#{totalItemCount}"
+          .children('.plugmixer-playlist-syncinfo').text "#{remainingCount}/#{totalItemCount}"

         if media.length <= 0 && Object.keys(youtubePlaylistItems).length <= 0
           $('.plugmixer-playlist').removeClass('plugmixer-playlist-syncing')
@@ -864,7 +864,7 @@
             resource:
               snippet:
                 playlistId: syncedPlaylist.youtube
-                resourceId:
+                resourceId:
                   kind: "youtube#video"
                   videoId: m.cid
               contentDetails:


Re-enabled deamon.

Re-enabled deamon.

--- app.coffee
+++ app.coffee
@@ -66,22 +66,20 @@
       queue.subscribe { ack: false }, (message, headers, deliveryInfo) ->
         fayeCli.publish message.channel, message.data

+if app_env == "production"

-startServer()
-# if app_env == "production"
+  daemon.daemonize
+    stdout: config.logFile,
+    config.pidFile, (err, pid) ->

-#   daemon.daemonize
-#     stdout: config.logFile,
-#     config.pidFile, (err, pid) ->
+      return console.log("Master: error starting daemon: " + err) if err
+      console.log "Daemon started successfully with pid: " + pid

-#       return console.log("Master: error starting daemon: " + err) if err
-#       console.log "Daemon started successfully with pid: " + pid
+      daemon.closeStdin()
+      startServer()

-#       daemon.closeStdin()
-#       startServer()
-
-# else
-#   startServer()
+else
+  startServer()


Add AppFog mongodb configuration

Add AppFog mongodb configuration

--- app.coffee
+++ app.coffee
@@ -1,4 +1,4 @@
-port = process.env.VMC_APP_PORT || 3000
+port = process.env.APP_PORT || 3000
 host = process.env.APP_HOST || "localhost"

 require('zappajs') host, port, ->
@@ -39,7 +39,9 @@
       mongoose.connect "mongodb://#{host}/#{manifest.name}-dev"
       @use errorHandler: {dumpExceptions: on, showStack: on}
     production: =>
-      mongoose.connect "mongodb://#{host}/#{manifest.name}"
+      services = JSON.parse process.env.VCAP_SERVICES
+      mongo = services['mongodb-1.8'][0]['credentials']
+      mongoose.connect "mongodb://#{mongo.username}:#{mongo.password}@#{mongo.hostname}:#{mongo.port}/#{mongo.db}"
       @use 'errorHandler'

   @get '/': ->


spreadsheet: don't show unreleased on materials

--- web/volume/spreadsheet.coffee
+++ web/volume/spreadsheet.coffee
@@ -490,8 +490,9 @@
             when 'name'
               v ?= ''
             when 'release'
-              cn = constants.release[v]
-              cell.className = cn + ' release icon hint-release-' + cn
+              if v || !slot?.top
+                cn = constants.release[v]
+                cell.className = cn + ' release icon hint-release-' + cn
               cell.classList.add('null') if slot?.top
               v = ''
             when 'date'


Remove menu

Remove menu

--- menus/passenger-restart.cson
+++ menus/passenger-restart.cson
@@ -1,15 +0,0 @@
-# See https://atom.io/docs/latest/hacking-atom-package-word-count#menus for more details
-'menu': [
-  {
-    'label': 'Packages'
-    'submenu': [
-      'label': 'Passenger'
-      'submenu': [
-        {
-          'label': 'Restart'
-          'command': 'passenger-restart:restart'
-        }
-      ]
-    ]
-  }
-]


Closes #2316; Send test mail will block the server

--- packages/rocketchat-lib/server/methods/sendSMTPTestEmail.coffee
+++ packages/rocketchat-lib/server/methods/sendSMTPTestEmail.coffee
@@ -6,6 +6,8 @@
 		user = Meteor.user()
 		unless user.emails?[0]?.address
 			throw new Meteor.Error 'invalid-email', "[methods] sendSMTPTestEmail -> Invalid e-mail"
+
+		this.unblock()

 		Email.send
 			to: user.emails[0].address


Put the object with in given boundries

Put the object with in given boundries

--- components/dia/kddiascene.coffee
+++ components/dia/kddiascene.coffee
@@ -33,6 +33,11 @@
     container.on "HighlightDia",      @bound "highlightLines"

     @containers.push container
+
+    padding = (container.getOption 'draggable')?.containment?.padding
+    if padding
+      pos.x = Math.max padding, pos.x ? 0
+      pos.y = Math.max padding, pos.y ? 0

     container.setX pos.x  if pos.x?
     container.setY pos.y  if pos.y?


Fix indentation (PASS)

Fix indentation (PASS)

--- lib-src/index.coffee
+++ lib-src/index.coffee
@@ -24,7 +24,7 @@
     return string unless possible.test string
     string.replace badChars, escChar

-beginningOfLine = /^/mg
+beginningOfLine = /^(?=.)/mg

 ind = (indent, string) ->
   string.replace beginningOfLine, indent


adding dbl click disabler for iPad

adding dbl click disabler for iPad

--- app/coffee/metamenu.coffee
+++ app/coffee/metamenu.coffee
@@ -20,6 +20,12 @@

   $('.settingsPanel .trigger').first().bind( clickEvent, (event)->
     $.publish('toggleSettings', [this])
+  )
+
+  # ipad doubleclick remover for left panel
+  $('.leftPanel a').bind( clickEvent, (event)->
+    $(event.currentTarget).preventDefault()
+    window.location = $(event.currentTarget).attr('href')
   )

   appearancePanel = new AppearancePanel('.appearancePanel')


Add can_destroy method to Fact

Add can_destroy method to Fact

Replaced 'is_mine' in the toJSON

--- core/app/backbone/models/fact.coffee
+++ core/app/backbone/models/fact.coffee
@@ -46,7 +46,7 @@

   has_evidence: -> @get('evidence_count') > 0

-  can_destroy: -> @is_mine() && !@has_evidence? # WHAT?! See issue https://github.com/Factlink/core/issues/1024
+  can_destroy: -> @is_mine() && !@has_evidence()

   factUrlHost: ->
     fact_url = @get('fact_url')
@@ -56,6 +56,6 @@

   toJSON: ->
     _.extend super(),
-      is_mine: @is_mine()
+      can_destroy: @can_destroy()
       fact_url_host: @factUrlHost()
       fact_url_title: @get('fact_title') || @factUrlHost()


Clarified HTML Parsing

Clarified HTML Parsing

--- gh-book.coffee
+++ gh-book.coffee
@@ -102,6 +102,8 @@
       html = html.replace(/body>/g, "prefix-body>")

       html = html.replace(/<html/g, "<prefix-html")
+      # Search for the exact element `<head>` since otherwise it could be
+      # confused with `<header>`.
       html = html.replace(/<head>/g, "<prefix-head>")
       html = html.replace(/<body/g, "<prefix-body")


Refactor: replace `this` with `@`

Refactor: replace `this` with `@`

--- assets/javascripts/contact.coffee
+++ assets/javascripts/contact.coffee
@@ -4,17 +4,17 @@
   .click (event)->
     $ '.form-control'
       .each ->
-        $(this.parentElement)
+        $(@.parentElement)
           .removeClass 'has-feedback'
           .addClass 'has-feedback'
         if this.value is ''
-          $(this.parentElement)
+          $(@.parentElement)
             .removeClass 'has-error'
             .addClass 'has-error'
             event
               .preventDefault()
         else
-            $(this.parentElement)
+            $(@.parentElement)
               .removeClass 'has-success'
               .addClass 'has-success'
           return


fix: test case

fix: test case

--- tests/integration/components/file-details-test.coffee
+++ tests/integration/components/file-details-test.coffee
@@ -13,4 +13,4 @@

   @render hbs """{{file-details}}"""

-  assert.equal @$().text().trim(), 'File DetailsHigh: Medium: Low: Passed: Unknown: created onversion codeReport Password  CopyPDF ReportVulnerability Details'
+  assert.equal @$().text().trim(), 'File DetailsHigh: Medium: Low: Passed: Unknown: created onversion codeSelected DeviceNo PreferenceSelected VersionReport Password  CopyPDF ReportVulnerability Details'


using nodeknockout.com

using nodeknockout.com

--- models/person.coffee
+++ models/person.coffee
@@ -9,7 +9,7 @@
     everyauth: { User: () -> Person }
   github:
     everyauth:
-      myHostname: 'http://localhost:8000'
+      myHostname: 'http://nodeknockout.com'
       appId: env.secrets.github_app_id
       appSecret: env.secrets.github_secret
       redirectPath: '/'


Icons: Fix Rotom formes.

Icons: Fix Rotom formes.

--- client/app/js/concerns/images.coffee
+++ client/app/js/concerns/images.coffee
@@ -1464,11 +1464,11 @@
   },
   "Rotom": {
     "default": 479,
-    "fan": NON_DEFAULT_FORMES_OFFSET + 68,
-    "frost": NON_DEFAULT_FORMES_OFFSET + 69,
-    "heat": NON_DEFAULT_FORMES_OFFSET + 70,
-    "mow": NON_DEFAULT_FORMES_OFFSET + 71,
-    "wash": NON_DEFAULT_FORMES_OFFSET + 72
+    "fan": NON_DEFAULT_FORMES_OFFSET + 52,
+    "frost": NON_DEFAULT_FORMES_OFFSET + 53,
+    "heat": NON_DEFAULT_FORMES_OFFSET + 54,
+    "mow": NON_DEFAULT_FORMES_OFFSET + 55,
+    "wash": NON_DEFAULT_FORMES_OFFSET + 56
   },
   "Rufflet": {
     "default": 627


Removing bad grammar dir

Removing bad grammar dir

--- grammar/d.cson
+++ grammar/d.cson
@@ -1,25 +0,0 @@
-'fileTypes' : [
-  'd'
-  'di'
-]
-'name': 'D'
-'scopeName': 'source.d'
-'patterns' : [
-  {
-    # control keywords
-    'name': 'keyword.control.untitled'
-    'match': '\b(if|while|for|return)\b'
-  }
-  {
-    # double-quoted strings with escapes
-    'name': 'string.quoted.double.untitled'
-    'begin': '"'
-    'end': '"'
-    'patterns': [
-      {
-        'name': 'constant'
-        'match': '\\.'
-      }
-    ]
-  }
-]


More warnings

More warnings

--- js/outer/docs.coffee
+++ js/outer/docs.coffee
@@ -80,10 +80,14 @@
       category: cx.category or null
       title_with_child_count: cx.title + (if children.length then " (#{children.length})" else "")

+    if result.children.length and result.lastUpdated
+      console.warn "#{uriFragment} has children but has lastUpdated"
+
     unless result.category
       #console.warn "#{uriFragment} should have a subtitle" unless result.subtitle
       console.warn "#{uriFragment} must have a title" unless result.title
-      console.warn "#{uriFragment} must have a lastUpdated" unless result.lastUpdated
+      unless result.lastUpdated or result.children.length or result.slug == "front_page"
+        console.warn "#{uriFragment} must have a lastUpdated"
     result

   viewContext: (cx) =>


allowImages (giphy)

allowImages (giphy)

--- modules/giphy.coffee
+++ modules/giphy.coffee
@@ -9,6 +9,7 @@
     @chance = new Chance()

     @registerCommand 'giphy', { aliases: ['gif'], allowDM: true }, (msg, q)=>
+      return unless d.data.allowImages
       try
         { data } = await Giphy.get('search', {
           json: true, qs: { q, api_key: 'dc6zaTOxFJmzC' }


'Updating for version 0.12.4dev12'

'Updating for version 0.12.4dev12'

--- bokehjs/src/coffee/version.coffee
+++ bokehjs/src/coffee/version.coffee
@@ -1 +1 @@
-export version = '0.12.4dev11'
+export version = '0.12.4dev12'


'Updating for version 0.12.5dev14'

'Updating for version 0.12.5dev14'

--- bokehjs/src/coffee/version.coffee
+++ bokehjs/src/coffee/version.coffee
@@ -1 +1 @@
-export version = '0.12.5dev13'
+export version = '0.12.5dev14'


Fixed success function definition

Fixed success function definition

--- core/app/backbone/models/wheel.coffee
+++ core/app/backbone/models/wheel.coffee
@@ -103,7 +103,7 @@
     $.ajax
       type: "DELETE"
       url: "/facts/#{fact_id}/opinion.json"
-      success: (data) =>
+      success: (data, status, response) =>
         @updateTo data.authority, data.opinion_types
         mp_track "Factlink: De-opinionate",
           factlink: fact_id


adding basic test for iterator

adding basic test for iterator

--- tests/test_operations.coffee
+++ tests/test_operations.coffee
@@ -19,6 +19,10 @@
          assert.ok not err, err
          done()

+   tearDown: (done) ->
+      leveldb.DB.destroyDB(@path, {})
+      done()
+
    'getting and putting data': (test) ->
       # put two keys and then ensure that we can each correctly
       d1 = defer.toDeferred @db.put, "1", "the data"
@@ -37,8 +41,39 @@
       d.addCallback(assert_val, "2", "more data")

       d.addErrback (err) ->
-         console.log err
+         console.log err.message.stack
+         err
+      d.addCallback () ->
+         test.done()
+
+   'iterator': (test) ->
+      # put several keys into the database and then iterate over them
+      d1 = defer.toDeferred @db.put, "1", "the data"
+      d2 = defer.toDeferred @db.put, "2", "more data"
+
+      d = defer.DeferredList([d1, d2])
+
+      d.addCallback () =>
+         d3 = new defer.Deferred()
+         iterator = @db.newIterator({})
+         keys = []
+
+         iterator.seekToFirst () ->
+            while iterator.valid()
+               key = iterator.key().toString('utf8')
+               keys.push(key)
+               iterator.next()
+            d3.callback()
+
+            assert.equal(keys[0], "1")
+            assert.equal(keys[1], "2")
+
+         return d3
+
+      d.addErrback (err) ->
+         console.log err.message.stack
          err
       d.addCallback () ->
          test.done()
 })
+


Add safety checks for abort and close functions

--- components/UrlToTempFile-node.coffee
+++ components/UrlToTempFile-node.coffee
@@ -78,11 +78,12 @@
       endStream = (error) ->
         return if endByError
         endByError = true
-        req.abort()
+        tmpFile.removeCallback()
+        error.url = url
+        log.err error
+        req.abort() if req.abort
+        return callback error unless stream.close
         stream.close ->
-          tmpFile.removeCallback()
-          error.url = url
-          log.err error
           return callback error
       req.on 'response', (resp) ->
         if resp.statusCode is 200


Fixing misidentification of Lisp buffer

Fixing misidentification of Lisp buffer

--- lib/atom-slime.coffee
+++ lib/atom-slime.coffee
@@ -52,12 +52,12 @@

     # Keep track of all Lisp editors
     @subs.add atom.workspace.observeTextEditors (editor) =>
-      if editor.getGrammar().name.search /Lisp/
+      if editor.getGrammar().name.match /Lisp/i
         ase = new AtomSlimeEditor(editor, @views.statusView, @swank)
         @ases.add ase
       else
         editor.onDidChangeGrammar =>
-          if editor.getGrammar().name.search /Lisp/
+          if editor.getGrammar().name.match /Lisp/i
             ase = new AtomSlimeEditor(editor, @views.statusView, @swank)
             @ases.add ase


Remove log line

Remove log line

--- lib/find-view.coffee
+++ lib/find-view.coffee
@@ -282,7 +282,6 @@
       atom.beep()

   markersUpdated: (@markers) =>
-    console.log 'updated', markers
     @findError = null
     @updateOptionButtons()
     @updateResultCounter()


refactor

refactor

--- lib/functions.coffee
+++ lib/functions.coffee
@@ -3,8 +3,8 @@
 module.exports =
   register: (params) ->
     url = params.url
-    method = params.method
+    method = params.method.toLowerCase()
     handle = params.handle
     app = config.get('app')
     prefix = config.get('prefix')
-    app[method.toLowerCase()]("#{prefix}#{url}", handle)
+    app[method]("#{prefix}#{url}", handle)


HUB-339 : define ZMQ_MAX_SOCKETS if undefined

--- lib/hubiquitus.coffee
+++ lib/hubiquitus.coffee
@@ -35,7 +35,7 @@
 factory = require "./hfactory"

 # Set ZMQ_MAX_SOCKETS to the highest possible value because hubiquitus uses a lot of sockets.
-if process.env.ZMQ_MAX_SOCKETS <= 0
+if not process.env.ZMQ_MAX_SOCKETS or process.env.ZMQ_MAX_SOCKETS <= 0
   process.env.ZMQ_MAX_SOCKETS = 1000000

 exports.Actor = require "./actor/hactor"


IDE: code style fixes

IDE: code style fixes

--- client/ide/RealTimeManager.coffee
+++ client/ide/RealTimeManager.coffee
@@ -180,11 +180,11 @@
           @bindListListeners instance

   textInserted:(string, e) ->
-    unless @isDisposed
-      @emit 'TextInsertedIntoString', string, e
+    return  if @isDisposed
+    @emit 'TextInsertedIntoString', string, e

   textDeleted:(string, e)=>
-    return if @isDisposed
+    return  if @isDisposed
     @emit 'TextDeletedFromString', string, e

   bindStringListeners: (string) ->
@@ -197,7 +197,7 @@

   mapValueChanged: (map, v) ->
-    return if @isDisposed
+    return  if @isDisposed
     @emit 'MapValueChanged', map, v

   bindMapListeners: (map) ->
@@ -207,15 +207,15 @@
     map.removeEventListener gapi.drive.realtime.EventType.VALUE_CHANGED, (v) => @mapValueChanged map, v

   listValueAdded: (list, v)->
-    return if @isDisposed
+    return  if @isDisposed
     @emit 'ValuesAddedToList', list, v

   listValueRemoved: (list, v)->
-    return if @isDisposed
+    return  if @isDisposed
     @emit 'ValuesRemovedFromList', list, v

   listValueSet:(list, v)=>
-    return if @isDisposed
+    return  if @isDisposed
     @emit 'ListValuesSet', list, v

   bindListListeners: (list) ->


change display function call

change display function call

--- shared/ironTableController.coffee
+++ shared/ironTableController.coffee
@@ -129,9 +129,9 @@
             for col, colObj of @_cols()
                 if not colObj.hide
                     colData.push
-                        value : colObj.func?(record) or record[col]
-                        aLink : colObj.link?(record)
-                        title : colObj.title?(record) or colObj.title
+                        value : colObj.display?(col, record) or record[col]
+                        aLink : colObj.link?(col, record)
+                        title : colObj.title?(col, record) or colObj.title

             recordData.push
                 colData: colData
@@ -208,7 +208,7 @@

                 if col["staticOn_#{type}"]
                     col.static = true
-                    col.value = col.func?(record) or record?[key]
+                    col.value = col.display?(record) or record?[key]

                 col.header = (col.header || key).capitalize()
                 col.key = key


Updated comment

Updated comment

--- client/src/app/model/cache.coffee
+++ client/src/app/model/cache.coffee
@@ -7,6 +7,7 @@

 # Saves data in a LocalStorage LRU cache
 # TODO: use polyfill for LocalStorage?
+# TODO: use IndexedDB for more space
 angular.module("gamEvolve.model.cache", [])
 .factory 'cache', ->
   # Saves in cache, or throws exception


atom's event kit will only emit a single argument, so pass cols and rows as an object

--- lib/term-view.coffee
+++ lib/term-view.coffee
@@ -133,7 +133,7 @@
       console.error error
       return

-    @emitter.emit 'resize', cols, rows
+    @emitter.emit 'resize', {cols, rows}

   titleVars: ->
     bashName: last @opts.shell.split '/'


rm double connect for terminal / wait for authentication before activating rest of ide, closes #326

--- lib/learn-ide.coffee
+++ lib/learn-ide.coffee
@@ -15,15 +15,11 @@

 module.exports =
   activate: (state) ->
-    @loadCredentials()
+    @waitForAuth = auth().then =>
+      @loadCredentials()
+      @activateIDE(state)

-    auth().then =>
-      @loadCredentials()
-      if not @term.isConnected
-        @term.updateToken(@oauthToken)
-        @term.connect()
-
-
+  activateIDE: (state) ->
     @isTerminalWindow = (localStorage.get('popoutTerminal') == 'true')
     if @isTerminalWindow
       window.resizeTo(750, 500)
@@ -111,7 +107,8 @@
     @vmPort = atom.config.get('learn-ide.vmPort')

   consumeStatusBar: (statusBar) ->
-    statusBar.addRightTile(item: @statusView, priority: 5000)
+    @waitForAuth.then =>
+      statusBar.addRightTile(item: @statusView, priority: 5000)

   serialize: ->
     termViewState: @termView.serialize()


:lipstick:

:lipstick:

--- lib/vim-state.coffee
+++ lib/vim-state.coffee
@@ -92,10 +92,8 @@
       return if @operationStack.isProcessing()
       someSelection = haveSomeSelection(@editor.getSelections())
       switch
-        when @isMode('visual') and (not someSelection)
-          @activate('normal')
-        when @isMode('normal') and someSelection
-          @activate('visual', 'characterwise')
+        when @isMode('visual') and (not someSelection) then @activate('normal')
+        when @isMode('normal') and someSelection then @activate('visual', 'characterwise')
       @showCursors()

     selectionWatcher = null


Comments.

Comments.

--- library/index.coffee
+++ library/index.coffee
@@ -15,20 +15,20 @@
   operation = new miniLockLib.DecryptOperation params
   operation.start(callback)

-# Expose [secret phrase](SecretPhrase.html) and
-# [email address](EmailAddress.html) acceptance tests.
+# Exports the [secret phrase](SecretPhrase.html) and
+# [email address](EmailAddress.html) modules.
 miniLockLib.SecretPhrase = require "./SecretPhrase"
 miniLockLib.EmailAddress = require "./EmailAddress"

-# Expose [identification](ID.html) functions.
+# Exports the [identification](ID.html) module.
 miniLockLib.ID = require "./ID"

-# Expose crypto operation constructors.
+# Exports the miniLock crypto operation constructors.
 miniLockLib.KeyPairOperation = require "./KeyPairOperation"
 miniLockLib.EncryptOperation = require "./EncryptOperation"
 miniLockLib.DecryptOperation = require "./DecryptOperation"

-# Expose special extras.
+# Exports special extras.
 miniLockLib.Base58  = require "./Base58"
 miniLockLib.BLAKE2s = require "./BLAKE2s"
 miniLockLib.NaCl    = require "./NaCl"


Fixing typo

Fixing typo

--- source/molecule/navigation.coffee
+++ source/molecule/navigation.coffee
@@ -2,7 +2,7 @@

   @template """<nav class="{{style}}"></nav>"""

-  available: ["label", "input", "textarea", "select", "button"]
+  available: ["button", "link"]

   constructor: ->
     @default =


revise comments; return w/out options

revise comments; return w/out options

--- lib/read-certs.coffee
+++ lib/read-certs.coffee
@@ -4,15 +4,21 @@

 module.exports = (options) ->

+  unless options? then return
+
   for key in [ 'ca', 'key', 'cert' ]
+
+    # TODO: if value is an array then process each value in the array

     path = options[key]

-    # TODO: if Array.isArray we could pass as args to resolve...
+    # assume a string value is a path we should read
     if typeof path is 'string'

+      # resolve to absolute path
       path = corepath.resolve path

+      # try reading the file content and storing back into options
       try
         content = fs.readFileSync path
         options[key] = content


Issue #36728 - Inputs inside disabled fieldset are not submited on remote: true forms

--- actionview/app/assets/javascripts/rails-ujs/utils/form.coffee
+++ actionview/app/assets/javascripts/rails-ujs/utils/form.coffee
@@ -11,6 +11,7 @@

   inputs.forEach (input) ->
     return if !input.name || input.disabled
+    return if input.closest('fieldset[disabled]')
     if matches(input, 'select')
       toArray(input.options).forEach (option) ->
         params.push(name: input.name, value: option.value) if option.selected


provide keys for React

provide keys for React

--- app/coffee/game.coffee
+++ app/coffee/game.coffee
@@ -343,12 +343,14 @@
     {button, div, select} = React.DOM
     div {className: 'board_nav_block'},
         [(select {
-           className: 'move_select',
+           key: 'movelist'
+           className: 'move_select'
            onChange: @onSelectChange
            onInput: @onSelectChange
            onKeyUp: @onSelectKeyUp
            value: @getViewingMove()}, @getOptions()),
          (button {
+           key: 'resetbutton'
            className: 'reset_button'
            disabled: @props.resetWouldDoNothing
            onClick: @props.resetCallback}, "Reset view to latest move")]


Throw a 404 if the username does not match the user on the channel (closes #1237)

--- apps/channel/routes.coffee
+++ apps/channel/routes.coffee
@@ -44,6 +44,12 @@
     ]) ->
       if channel.get('class') is 'User'
         return res.redirect 301, "/#{channel.get 'slug'}"
+
+      if channel.get('user')?.slug isnt req.params.username
+        err = new Error
+        err.status = 404
+        err.message = 'Not Found'
+        return next err

       res.locals.sd.CHANNEL = channel.toJSON()
       res.locals.sd.COLLABORATORS = channel.related().collaborators.toJSON()


parse exif orientation

parse exif orientation

--- app/assets/javascripts/uploadcare/utils/image-processor.coffee
+++ app/assets/javascripts/uploadcare/utils/image-processor.coffee
@@ -33,7 +33,7 @@
         img.onerror = null  # do not fire when set to blank
         df.notify(.10)

-        ns.readExif(file).always (exif) ->
+        ns.getExif(file).always (exif) ->
           df.notify(.2)
           isJPEG = @state() is 'resolved'

@@ -54,7 +54,7 @@
                 df.notify(.9)
                 # console.log('to blob: ' + (new Date() - start))
                 if exif
-                  op = ns.replaceJpegChunk(blob, 0xe1, [exif])
+                  op = ns.replaceJpegChunk(blob, 0xe1, [exif.buffer])
                   op.done(df.resolve)
                   op.fail ->
                     df.resolve(blob)
@@ -205,18 +205,44 @@
     df.promise()

-  ns.readExif = (file) ->
+  ns.getExif = (file) ->
     exif = null
     op = ns.readJpegChunks(file)
     op.progress (pos, l, marker, view) ->
       if not exif and marker == 0xe1
         if view.byteLength >= 14
           if view.getUint32(0) == 0x45786966 and view.getUint16(4) == 0
-            exif = view.buffer
+            exif = view
     return op.then ->
       return exif
     , (reason) ->
       return $.Deferred().reject(exif, reason)
+
+
+  ns.parseExifOrientation = (exif) ->
+    if (
+      exif.byteLength < 14 or
+      exif.getUint32(0) != 0x45786966 or
+      exif.getUint16(4) != 0 or
+      exif.getUint16(8) != 0x002A
+    )
+      return null
+    if exif.getUint16(6) == 0x4949
+      little = true
+    else if exif.getUint16(6) == 0x4D4D
+      little = false
+    else
+      return null
+
+    offset = 8 + exif.getUint32(10, little)
+    count = exif.getUint16(offset - 2, little)
+    for i in [0...count]
+      if exif.byteLength < offset + 10
+        return null
+      if exif.getUint16(offset, little) == 0x0112
+        return exif.getUint16(offset + 8, little)
+      offset += 12
+

   ns.hasTransparency = (img) ->
     pcsn = 50


rename command

rename command

--- keymaps/atomizr.cson
+++ keymaps/atomizr.cson
@@ -1,5 +1,5 @@
 'atom-text-editor':
   'ctrl-a ctrl-a': 'atomizr:automatic-conversion'
   'ctrl-a ctrl-s': 'atomizr:convert-atom-to-sublime-text'
-  'ctrl-s ctrl-a': 'atomizr:convert-sublime-text-to-atom'
+  'ctrl-s ctrl-a': 'atomizr:convert-sublime-text-completions-to-atom'
   'ctrl-c ctrl-c': 'atomizr:convert-atom-format'


Fix CloseUrl RegExp

Fix CloseUrl RegExp

--- client/app/utils/api_utils.coffee
+++ client/app/utils/api_utils.coffee
@@ -14,7 +14,7 @@
     return router.current.firstPanel?.action in actions

-module.exports =
+module.exports = Utils =

     debugLogs: []
@@ -151,8 +151,8 @@

     messageClose: ->
         href = window.location.href
-        closeUrl = href.replace /\/message\/[^\/]*\//gi, ''
-        closeUrl = closeUrl.replace /\/conversation\/[^\/]*\/[^\/]*\//gi, ''
+        closeUrl = href.replace /\/message\/[\w-]+/gi, ''
+        closeUrl = closeUrl.replace /\/conversation\/[\w-]+\/[\w-]+/gi, ''
         window.location.href = closeUrl

@@ -174,6 +174,7 @@
                     smart_count: 1
         if (not confirm)
             MessageActionCreator.delete {messageID}
+            Utils.messageClose()
         else
             modal =
                 title       : t 'app confirm delete'
@@ -183,6 +184,7 @@
                 action      : ->
                     MessageActionCreator.delete {messageID}
                     LayoutActionCreator.hideModal()
+                    Utils.messageClose()
             LayoutActionCreator.displayModal modal


Remove things based on review comments

Remove things based on review comments

--- lib/tag-finder.coffee
+++ lib/tag-finder.coffee
@@ -97,9 +97,6 @@
             # Subtract < and tag name suffix from range
             # startRange = range.translate([0, 1], [0, -(match[2].length + match[3].length)])

-          until startRange.end.column > 0 # if the tag spans multiple lines, the end.column is negative, so iterate until it's not.
-            startRange.end.row -= 1 # move the end up one row
-            startRange.end.column = @editor.getBuffer().lineLengthForRow(startRange.end.row) + startRange.end.column + 2 # and set the column
           stop()
       else
         unpairedCount++
@@ -160,9 +157,6 @@
   findEnclosingTags: (fullRange=false) ->
     if ranges = @findStartEndTags(fullRange)
       if @isTagRange(ranges.startRange) and @isTagRange(ranges.endRange)
-        if ranges.startRange.start.row > ranges.endRange.start.row
-          # If the endRange occurs after the startRange in the buffer, switch them
-          [ranges.startRange, ranges.endRange] = [ranges.endRange, ranges.startRange]
         return ranges

     null


Add styling classes to giOverflow

Add styling classes to giOverflow

--- client/directives/overflow.coffee
+++ client/directives/overflow.coffee
@@ -37,7 +37,7 @@
             appendMore = ''
             appendLess = ''

-          elem.html('
' + text + '
')
+          elem.html('
' + text + '
')

           # If text has overflow
           if isOverflow(elem)
@@ -49,12 +49,12 @@
             # until there is no overflow
             while (not isTruncated) and bindArray.length > 0
               bindArray.pop()
-              elem.html('
' + bindArray.join(" ") + ellipsisSymbol + '
' + appendMore)
+              elem.html('
' + bindArray.join(" ") + ellipsisSymbol + '
' + appendMore)
               if (elem[0].scrollHeight < initialMaxHeight) or
               (not isOverflow(elem))
                 isTruncated = true
           else if showingAll
-            elem.html('
' + text + '
' + appendLess)
+            elem.html('
' + text + '
' + appendLess)

           if renderControls
             elem.find('a').bind "click", (e) ->


Fix bug.

Fix bug.

--- app/server/js/app.coffee
+++ app/server/js/app.coffee
@@ -51,7 +51,7 @@

     api.addToExpress app, (route, req, res, promise) ->
       promise
-        .then (json) -> res.json json
+        .then (json) -> res['json'] json
         .thenCatch (reason) =>
           onError route, reason
           res['status'](500)['json'] {}


Fix german

Fix german

Fix german translation of Han Solo (TFA)

--- coffeescripts/cards-de.coffee
+++ coffeescripts/cards-de.coffee
@@ -774,7 +774,7 @@
         "Rey":
             text: """Sobald du angreifst oder verteidigst, darfst du bis zu 2 deiner Leerseiten neu würfeln, falls das feindliche Schiff innerhalb deines Feuerwinkels ist."""
         'Han Solo (TFA)':
-            text: '''Sobald du beim Spielaufbau platziert wirst, kannst du irgendwo auf der Spielfläche von Reichweite 1-3 zu feindlichen Schiffen platziert werden.'''
+            text: '''Sobald du beim Spielaufbau platziert wirst, kannst du irgendwo auf der Spielfläche jenseits von Reichweite 1-3 zu feindlichen Schiffen platziert werden.'''
         'Chewbacca (TFA)':
             text: '''Nachdem ein anderes freundliches Schiff in Reichweite 1-3 zerstört worden (aber nicht geflohen) ist, darfst du einen Angriff durchführen.'''
         'Resistance Sympathizer':


Scaffolding commands. v 0.10.23

Scaffolding commands. v 0.10.23


Fixed issues with .ino files

Fixed issues with .ino files

--- lib/views/compile-errors-view.coffee
+++ lib/views/compile-errors-view.coffee
@@ -71,18 +71,22 @@
     if @hasParent()
       @detach()

+  fixInoFile: (filename) ->
+    fs ?= require 'fs-plus'
+    if fs.existsSync filename
+      return filename
+    else
+      return filename.replace '.cpp', '.ino'
+
   viewForItem: (item) ->
+    self = @
     $$ ->
       @li class: 'two-lines', =>
         @div class: 'primary-line', item.message
-        @div class: 'secondary-line', item.file + ':' + item.row + ':' + item.col
+        @div class: 'secondary-line', self.fixInoFile(item.file) + ':' + item.row + ':' + item.col

   confirmed: (item) ->
-    fs ?= require 'fs-plus'
-    if fs.existsSync item.file
-      filename = item.file
-    else
-      filename = item.file.replace '.cpp', '.ino'
+    filename = @fixInoFile item.file

     # Open file with error in editor
     opening = atom.workspaceView.open filename, { searchAllPanes: true }


Avoid breaking when calling lstat on virtual paths

Resolves atom/tree-view#927.

--- lib/tree-view.coffee
+++ lib/tree-view.coffee
@@ -276,6 +276,7 @@

     @roots = for projectPath in atom.project.getPaths()
       stats = fs.lstatSyncNoException(projectPath)
+      continue unless stats
       stats = _.pick stats, _.keys(stats)...
       for key in ["atime", "birthtime", "ctime", "mtime"]
         stats[key] = stats[key].getTime()


Fix user's email's uniqueness validation

--- app/models/user.coffee
+++ app/models/user.coffee
@@ -66,17 +66,10 @@
   beforeUpdate: generateHash

   customCallbacks:
-    beforeValidate: (self) ->
+    beforeValidate: (User) ->
       (values, next) ->
-        self
+        User
         .findOneByEmail(values.email)
         .exec (err, user) ->
-          isValid = false
-
-          if !user
-            isValid = true
-          else if values.id? && user.id == values.id
-            isValid = true
-
-          global.uniqueEmail = isValid
+          global.uniqueEmail = !err && (!user || values.id == user.id)
           next()


Make events unique to each view

Make events unique to each view

--- src/scripts/helpers/backbone/views/attached/tooltip/tooltip.coffee
+++ src/scripts/helpers/backbone/views/attached/tooltip/tooltip.coffee
@@ -21,7 +21,7 @@
       @$owner = $(options.owner)

     onShow: () ->
-      @$owner.on "#{@trigger}.#{@type}", () => @toggle()
+      @$owner.on "#{@trigger}.#{@type}.#{@cid}", () => @toggle()

     toggle: () ->
       @reposition()
@@ -52,4 +52,4 @@
             'right': Math.floor($(document).outerWidth(true) - @$owner.offset().left)

     onBeforeClose: () ->
-      @$owner.off "#{@trigger}.#{@type}"
+      @$owner.off "#{@trigger}.#{@type}.#{@cid}"


Make ChineseIme work when switching search inputs

--- app/assets/javascripts/rglossa/components/centre/search_inputs/cwb_search_inputs.jsx.coffee
+++ app/assets/javascripts/rglossa/components/centre/search_inputs/cwb_search_inputs.jsx.coffee
@@ -78,14 +78,21 @@
   addPhraseButton: ->
     `<button className="btn add-phrase-btn" onClick={this.props.handleAddPhrase}>Or...</button>`

+  updateChineseIME: ->
+    $("input[type='text']").chineseInput
+      debug: false,
+      input:
+        initial: 'simplified',
+        allowChange: false,
+      allowHide: true,
+      active: $('#ime_check').prop('checked')
+
   componentDidMount: ->
-    $("input[type='text']").chineseInput
-      debug: false, # print debug messages
-      input:
-        initial: 'simplified', # or 'simplified'
-        allowChange: false, # allow transition between traditional and simplified
-      allowHide: true, # allow the chinese input to be switched off
-      active: false # whether or not the plugin should be active by default
+    @updateChineseIME()
+
+  componentDidUpdate: ->
+    $("input[type='text']").unbind()
+    @updateChineseIME()

   render: ->
@@ -117,6 +124,7 @@

     else if @state.statechart.pathContains('multiword')
       `
+        <ChineseIme corpus={this.props.corpus} />

           Simple |
           Extended |
@@ -139,6 +147,7 @@

     else
       `
+        <ChineseIme corpus={this.props.corpus} />

           Simple |
           Extended |


Remove a testing line

Remove a testing line

--- admin/static/coffee/namespaces/index.coffee
+++ admin/static/coffee/namespaces/index.coffee
@@ -33,11 +33,9 @@
         update_button_create_namespace: =>
             if databases.length is 0 and @can_create_namespace is true
                 @.$('.add-namespace').prop 'disabled', 'disabled'
-                @.$('.user_alert_space-cannot_create_namespace').html 'Bad boy'
                 @.$('.user_alert_space-cannot_create_namespace').show()
             else if databases.length > 0 and @can_create_namespace is false
                 @.$('.add-namespace').removeProp 'disabled'
-                @.$('.user_alert_space-cannot_create_namespace').html ''
                 @.$('.user_alert_space-cannot_create_namespace').hide()

         render: (message) =>


replaced calcOverlayPosition, trigger=manual in tutor-popover

--- src/components/tutor-popover.cjsx
+++ src/components/tutor-popover.cjsx
@@ -105,7 +105,7 @@

   guessPlacement: ->
     {windowImpl} = @props
-    {overlayLeft} = @refs.popper.calcOverlayPosition()
+    overlayLeft = React.findDOMNode(@refs.popper).getBoundingClientRect().left
     midWindow = windowImpl.innerWidth / 2
     if overlayLeft > midWindow then 'left' else 'right'

@@ -144,7 +144,6 @@
       {...overlayProps}
       placement={placement}
       overlay={popover}
-      trigger='manual'
       ref='popper'>
       {children}
     </BS.OverlayTrigger>


chat: change delete modal to show loader on button

--- client/Social/Activity/views/privatemessage/deletemodal.coffee
+++ client/Social/Activity/views/privatemessage/deletemodal.coffee
@@ -2,16 +2,36 @@

   @create: (channel) ->

-    modal         = KDModalView.confirm
-      title       : 'Are you sure?'
-      description : 'Delete this conversation?'
-      ok          :
-        title     : 'Remove'
-        callback  : ->
+    removeFn = (modal) ->
+      removeButton = modal.buttons['Remove']
+      removeButton.showLoader()

+      channelId = channel.getId()
+
+      KD.remote.api.SocialChannel.delete {channelId}
+        .then ->
           modal.destroy()
+          KD.singletons.router.handleRoute '/Activity/Public'
+        .catch (args...) ->
+          KD.showError args...
+          removeButton.hideLoader()

-          channelId = channel.getId()
+    modal = new KDModalView
+      title      : 'Are you sure'
+      content    : """
+

+
Delete this conversation?

+

+        """
+      overlay    : yes
+      buttons    :
+        Remove   :
+          title  : 'Remove'
+          style  : 'modal-clean-red'
+          loader : { color: '#e94b35' }
+          callback : -> removeFn modal
+        Cancel   :
+          title  : 'Cancel'
+          style  : 'modal-cancel'
+          callback : -> modal.destroy()

-          KD.remote.api.SocialChannel.delete {channelId}
-            .catch KD.showError


Minor defines re-sorting.

Minor defines re-sorting.

--- src/defines.coffee
+++ src/defines.coffee
@@ -13,18 +13,18 @@
     # Turn off here to disable entirely (@release).
     developing: on

-    progressW: 360
-    progressH: 8
+    artH: 2912
+    mapH: 3152 # +240

     buttonW: 80
     buttonH: 30
+
+    deadzoneH: 100
+    shakeFallH: 300

     playerH: 72
     playerW: 72
     playerYOffset: 16

-    artH: 2912
-    mapH: 3152 # +240
-
-    deadzoneH: 100
-    shakeFallH: 300
+    progressW: 360
+    progressH: 8


KDFramework: this may break some forms (hopefully not), passing data is implemented to formwithfields

--- client/Framework/components/forms/KDFormViewWithFields.coffee
+++ client/Framework/components/forms/KDFormViewWithFields.coffee
@@ -30,28 +30,28 @@
       @buttonField.addSubView button = @createButton buttonOptions
       @buttons[buttonOptions.key] = button

-  createField:(data, field)->
-    {itemClass, title} = data
-    itemClass     or= KDInputView
-    data.cssClass or= ""
-    data.name     or= title
-    field or= new KDView cssClass : "formline #{data.name} #{data.cssClass}"
-    field.addSubView label = data.label = @createLabel(data) if data.label
+  createField:(fieldData, field)->
+    {itemClass, title} = fieldData
+    itemClass          or= KDInputView
+    fieldData.cssClass or= ""
+    fieldData.name     or= title
+    field or= new KDView cssClass : "formline #{fieldData.name} #{fieldData.cssClass}"
+    field.addSubView label = fieldData.label = @createLabel(fieldData) if fieldData.label
     field.addSubView inputWrapper = new KDCustomHTMLView cssClass : "input-wrapper"
-    inputWrapper.addSubView input = @createInput itemClass, data
-    if data.hint
+    inputWrapper.addSubView input = @createInput itemClass, fieldData
+    if fieldData.hint
       inputWrapper.addSubView hint  = new KDCustomHTMLView
-        partial  : data.hint
+        partial  : fieldData.hint
         tagName  : "cite"
         cssClass : "hint"
     @fields[title] = field
-    if data.nextElement
-      for key, next of data.nextElement
+    if fieldData.nextElement
+      for key, next of fieldData.nextElement
         next.title or= key
         @createField next, inputWrapper

-    if data.nextElementFlat
-      for key, next of data.nextElementFlat
+    if fieldData.nextElementFlat
+      for key, next of fieldData.nextElementFlat
         next.title or= key
         @createField next, field

@@ -64,7 +64,9 @@
       cssClass : @utils.slugify data.label

   createInput:(itemClass, options)->
-    @inputs[options.title] = input = new itemClass options
+    {data} = options
+    delete options.data  if data
+    @inputs[options.title] = input = new itemClass options, data
     return input

   createButton:(options)->


Fix memory usage bug

Fix memory usage bug

--- client/app/MainApp/filetree/itemsubviews/vmdetailsview.coffee
+++ client/app/MainApp/filetree/itemsubviews/vmdetailsview.coffee
@@ -44,7 +44,7 @@

     if info.state is "RUNNING"
       # Memory
-      mem = (info.memoryUsage / info.memoryLimit * 100).toFixed(2)
+      mem = ((info.memoryUsage * 100) / info.memoryLimit).toFixed(2)
       @labelRAM.updateTitle "#{mem}%"
       # RX
       @kcRun cmdRX, (err, out)=>


Colorize available packages heading as cyan

--- src/fetcher.coffee
+++ src/fetcher.coffee
@@ -47,7 +47,7 @@
         if options.argv.json
           console.log(JSON.stringify(packages))
         else
-          console.log "Available Atom packages (#{packages.length})"
+          console.log "#{'Available Atom packages'.cyan} (#{packages.length})"
           tree packages, ({name, version}) ->
             "#{name}@#{version}"
         options.callback()


code cleanup

code cleanup

--- lib/wp-phptidy.coffee
+++ lib/wp-phptidy.coffee
@@ -24,5 +24,3 @@

 			else
 		  		child_process.exec(__dirname + '/../vendor/wp-phptidy.php replace ' + filepath)
-
-


Add slashes to redirects

Add slashes to redirects

--- lib/www_routes.coffee
+++ lib/www_routes.coffee
@@ -261,7 +261,7 @@
       return www_methods.handle_error(req, res, "Invalid JSON for member changeset")
     www_methods.create_group req.session, group_update, (err, group) ->
       return www_methods.handle_error(req, res, err) if err?
-      return res.redirect("/groups/show/#{group.slug}")
+      return res.redirect("/groups/show/#{group.slug}/")

   utils.append_slash(app, "/groups/is_available")
   app.get '/groups/is_available/', (req, res) ->
@@ -311,7 +311,7 @@

       www_methods.update_group req.session, group, group_update, (err) ->
         return www_methods.handle_error(req, res, err) if err?
-        return res.redirect("/groups/show/#{group.slug}")
+        return res.redirect("/groups/show/#{group.slug}/")

   utils.append_slash(app, "/groups/join/[^/]+", ["get", "post"])
   app.get '/groups/join/:slug/', (req, res) ->


Don't hang if a transclusion couldn't be found

--- src/hercule.coffee
+++ src/hercule.coffee
@@ -45,7 +45,7 @@
             .replace /\n$/, ""

           input = input.replace "#{placeholder}", output
-          return done()
+        return done()
   , ->
     return cb input


So yeah the picture has to be removed at some point from the cache, and I'd say its when the picture's src is saved to the collection.

--- lib/client/autoform-slingshot.coffee
+++ lib/client/autoform-slingshot.coffee
@@ -93,6 +93,13 @@
       imgs = _.map( images, (image)-> image.src )
       imgs

+# Remove pictures from cache when saved to document.
+AutoForm.addHooks null,
+  onSuccess: ->
+    if @currentDoc and @currentDoc.pictures
+      _.each @currentDoc.pictures, (picture) ->
+        SlingshotAutoformFileCache.remove({src: picture.src});
+
 getCollection = (context) ->
   if typeof context.atts.collection == 'string'
     context.atts.collection = FS._collections[context.atts.collection] or window[context.atts.collection]


remove lastresponse

remove lastresponse

--- src/views/screens/shipping.coffee
+++ src/views/screens/shipping.coffee
@@ -158,7 +158,7 @@
     ).catch (err)=>
       console.log "shipping submit Error: #{err}"

-      res = @client.lastResponse.responseText
+      res = error.data
       if res.error.code == 'card-declined'
         @screenManagerObs.trigger Events.Confirm.Error, 'Sorry, your card was declined. Please check your payment information.'
       else


add onViewShow callback after new item created;

--- app/assets/javascripts/chr/core/view.coffee
+++ app/assets/javascripts/chr/core/view.coffee
@@ -124,6 +124,7 @@
           @_add_delete_button()
           chr.updateHash("#{ @closePath }/view/#{ @object._id }", true)
           @path = window.location.hash
+          @config.onViewShow?(@)
         onError: (errors) => @_save_error('Document is not created due to an error.', errors)


do not propogate click event when creating pop-up, better parameter id, box not focusing fixed

--- web/scripts/playerCodeEditor.coffee
+++ web/scripts/playerCodeEditor.coffee
@@ -139,6 +139,8 @@
             When the editor is clicked, we may or may not
             want to pop up a div for students to enter
             parameters into.
+            Return true: continue event propogation
+            Return false: stop event propogation
         ###
         if @parameterPopUp == undefined
             @parameterPopUp = jQuery('#parameter-pop-up')
@@ -149,22 +151,23 @@
             rowLength = line.length
             if rowLength == 0
                 @parameterPopUp.hide()
-                return
+                return true

             command = @interpreter.identifyCommand line
             if command == null
                 @parameterPopUp.hide()
-                return
+                return true

             numberOfInputs = @commands[command]['inputs']
             if numberOfInputs == 0
                 @parameterPopUp.hide()
-                return
+                return true

             @parameterPopUp.empty()
             @parameterPopUp.append '('
             for i in [1..numberOfInputs] by 1
-                @parameterPopUp.append "<input id='#{i}' type='text' size='5' class='pop-up-inside'>"
+                id = "#{command}-parameter-#{i}"
+                @parameterPopUp.append "<input id='#{id}' type='text' size='5' class='pop-up-inside'>"
                 if i != numberOfInputs
                     @parameterPopUp.append ','
             @parameterPopUp.append ')'
@@ -183,9 +186,12 @@
             @parameterPopUp.css 'left', rowLength * 6 + gutterOffset + editorOffset.left

             @parameterPopUp.show()
+            setTimeout (-> jQuery("##{command}-parameter-#{1}").focus(); return), 0
+            # jQuery('#1').submit((submitEvent) -> alert "WHAT")
+            return false
         else
             @parameterPopUp.hide()
-        return
+        return true

     popUpEditLine: (row, command) ->
         if @parameterPopUp == undefined


Fixed comment to be more correct ;-)

Fixed comment to be more correct ;-)

--- core/app/backbone/modules/discussion_modal_on_frontend.coffee
+++ core/app/backbone/modules/discussion_modal_on_frontend.coffee
@@ -17,8 +17,7 @@
     newClientModal.mainRegion.show new NDPDiscussionView model: fact

   # HACK: This assumes that we use "navigate url, true" for all url changes that
-  # leave the main regions alone (sidebar, mainRegion, etc)
-  DiscussionModalOnFrontend.loadUrlStopRouting = (fragment) ->
+  # originate from the discussion modal
     FactlinkApp.discussionModalRegion.close()

     if fragment == background_page_url


allow open_browser to take a uri/app option

--- lib/cli/watch.coffee
+++ lib/cli/watch.coffee
@@ -41,7 +41,10 @@
       res.watcher = w
       res.server = app.start(port)
       if project.config.open_browser and not args.no_open
-        open("http://localhost:#{port}/")
+        if project.config.open_browser == true
+          open("http://localhost:#{port}/")
+        else
+          open(project.config.open_browser)
     .yield(res)

 ###*


Stream output only if verbose mode.

Stream output only if verbose mode.

--- src/install.coffee
+++ src/install.coffee
@@ -73,7 +73,9 @@
       proxy = npm.config.get('https-proxy') or npm.config.get('proxy')
       installNodeArgs.push("--proxy=#{proxy}") if proxy

-      opts = {env, cwd: @atomDirectory, streaming: true}
+      opts = {env, cwd: @atomDirectory}
+      opts['streaming'] = true if @verbose
+
       @fork @atomNodeGypPath, installNodeArgs, opts, (code, stderr='', stdout='') ->
         if code is 0
           callback()
@@ -112,7 +114,9 @@
     env = _.extend({}, process.env, HOME: @atomNodeDirectory)
     @updateWindowsEnv(env) if config.isWin32()
     @addNodeBinToEnv(env)
-    installOptions = {env, streaming: true}
+    installOptions = {env}
+
+    installOptions['streaming'] = true if @verbose

     installGlobally = options.installGlobally ? true
     if installGlobally
@@ -460,7 +464,8 @@

     return @checkNativeBuildTools(callback) if options.argv.check

-    process.env.NODE_DEBUG = 'request' if options.argv.verbose
+    @verbose = options.argv.verbose
+    process.env.NODE_DEBUG = 'request' if @verbose

     installPackage = (name, callback) =>
       if name is '.'


Fix double confirmation before ajax call (#400)

--- assets/src/datagrid.coffee
+++ assets/src/datagrid.coffee
@@ -1,6 +1,6 @@
 # Non-ajax confirmation
 #
-$(document).on('click', '[data-datagrid-confirm]', (e) ->
+$(document).on('click', '[data-datagrid-confirm]:not(.ajax)', (e) ->
 	if not confirm($(e.target).closest('a').attr('data-datagrid-confirm'))
 		e.stopPropagation()
 		e.preventDefault()