implement proper cluster stop method

implement proper cluster stop method

--- src/decking.coffee
+++ src/decking.coffee
@@ -65,14 +65,8 @@
       @start cluster, done

     stop: (done) ->
-      [container] = @args
-      @stop container, done
-
-    cluster: (done) ->
-      [method, cluster] = @args
-      switch method
-        when "start" then @cluster_start cluster, done
-        when "stop" then @cluster_stop cluster, done
+      [cluster] = @args
+      @stop cluster, done

     status: (done) ->
       child_process.exec "docker ps", (err, stdout, stderr) ->
@@ -90,28 +84,45 @@

     resolveOrder @config, target, (list) ->

-      async.eachSeries list, (details, callback) ->
-        name = details.name
-        container = docker.getContainer name
-        container.inspect (err, data) ->
-          if not data.State.Running
-            log "Starting container #{name}"
-            container.start callback
-          else
-            log "Container #{name} already running..."
-            callback null
-      , done
-
-
-  stop: (container, done) ->
-    throw new Error("Please supply a container to stop") if not container
-
-    target = @config.containers[container]
-
-    throw new Error("Container #{container} does not exist in decking.json") if not target
-
-    container = docker.getContainer container
-    container.stop done
+      validateContainerPresence list, (err) ->
+        return done err if err
+
+        async.eachSeries list, (details, callback) ->
+          name = details.name
+          container = docker.getContainer name
+          container.inspect (err, data) ->
+            if not data.State.Running
+              log "Starting container #{name}"
+              container.start callback
+            else
+              log "Container #{name} already running..."
+              callback null
+        , done
+
+
+  stop: (cluster, done) ->
+    throw new Error "Please supply a cluster to stop" if not cluster
+
+    target = @config.clusters[cluster]
+
+    throw new Error "Cluster #{cluster} does not exist in decking.json"  if not target
+
+    resolveOrder @config, target, (list) ->
+
+      validateContainerPresence list, (err) ->
+        return done err if err
+
+        async.eachSeries list, (details, callback) ->
+          name = details.name
+          container = docker.getContainer name
+          container.inspect (err, data) ->
+            if data.State.Running
+              log "Stopping container #{name}"
+              container.stop callback
+            else
+              log "Container #{name} is not running..."
+              callback null
+        , done

   create: (container, done) ->
     # @TODO use the remote API when it supports -name and -link
@@ -152,33 +163,6 @@
           if depLength is 0
             doRun()

-  cluster_start: (cluster, done) ->
-    throw new Error("Please supply a cluster to start") if not cluster
-
-    target = @config.clusters[cluster]
-
-    throw new Error("Cluster #{cluster} does not exist in decking.json") if not target
-
-    log "Starting cluster #{cluster} with #{target.length} containers"
-
-    # @TODO get this in dependency order
-    async.eachSeries target, (container, callback) =>
-      @start container, callback
-    , done
-
-  cluster_stop: (cluster, done) ->
-    throw new Error("Please supply a cluster to stop") if not cluster
-
-    target = @config.clusters[cluster]
-
-    throw new Error("Cluster #{cluster} does not exist in decking.json") if not target
-
-    log "Stopping cluster #{cluster} with #{target.length} containers"
-
-    async.eachSeries target, (container, callback) =>
-      @stop container, callback
-    , done
-
   build: (image, done) ->

     throw new Error("Please supply an image name to build") if not image
@@ -257,3 +241,11 @@
   list = (containerDetails[item] for item in depTree.resolve())

   callback list
+
+validateContainerPresence = (list, done) ->
+  iterator = (details, callback) ->
+    name = details.name
+    container = docker.getContainer name
+    container.inspect callback
+
+  async.eachSeries list, iterator, done


commit

commit

--- lib/build/android-build-view.coffee
+++ lib/build/android-build-view.coffee
@@ -71,7 +71,7 @@
     @aliaspass.setText "test123"
     @url.setText "http://localhost:800/androiddown/android.zip"
     @scheme.setText "bundle"
-    @src.setText "./index.html"
+    @src.setText "exhibition/index.html"

   onClickIcon: ->
     openFile


fixed path escaping on windows ...again.

--- lib/connection/process/basic.coffee
+++ lib/connection/process/basic.coffee
@@ -74,7 +74,7 @@
       else
         @freePort().then (port) =>
           wrapPort = port+1
-          jlargs = [args..., '`"' + paths.script('boot.jl') + '`"', port]
+          jlargs = [args..., '"`"' + paths.script('boot.jl') + '`""', port]
           proc = child_process.spawn("powershell",
                                      ["-NoProfile", "-ExecutionPolicy", "bypass",
                                       "& \"#{paths.script "spawnInterruptible.ps1"}\"


quest/add: call initRealm() only once, on @activate()

--- www/src/views/quest/add.coffee
+++ www/src/views/quest/add.coffee
@@ -138,13 +138,6 @@
             tagLine = @$("[name=tags]").val()
             QuestModel::tagline2tags tagLine

-        initRealm: ->
-            id = @options.realm
-            unless id
-                userRealms = sharedModels.currentUser.get("realms")
-                id = userRealms[0] if userRealms and userRealms.length is 1
-            @updateRealm id
-
         setRealm: (id) ->
             @_realmId = id
             if id
@@ -167,10 +160,16 @@
             unless sharedModels.realms.length
                 sharedModels.realms.fetch().success => @activate()
                 return
+
+            id = @options.realm
+            unless id
+                userRealms = sharedModels.currentUser.get("realms")
+                id = userRealms[0] if userRealms and userRealms.length is 1
+            @setRealm id
+
             super

         render: ->
-            @initRealm()
             super
             @setRealmList @getRealmId()
             @setRealmSelect @getRealmId()


Whitespace cleaning

Whitespace cleaning

--- test/core/charts.coffee
+++ test/core/charts.coffee
@@ -270,5 +270,3 @@
         assert.equal chart.getHeight(), pixelRatio * defaultHeight

     #describe 'getStyles', ->
-
-


remove emitter from memory tests

remove emitter from memory tests

--- test/perf/memory-specs/bus.coffee
+++ test/perf/memory-specs/bus.coffee
@@ -1,9 +1,4 @@
 h = require('../memory-helper.coffee')
-
-h.setupSpec 'bus vs emitter', {
-  kefir: (Kefir) -> Kefir.emitter()
-  bacon: (Bacon) -> new Bacon.Bus()
-}

 h.setupSpec 'bus vs pool', {
   kefir: (Kefir) -> Kefir.pool()


added tests for selecting nodes and getting a subset of packages

Signed-off-by: Dominik Richter <b7323add517e187efe0283b76511b7ed762bfe13@gmail.com>

--- test/spec/controllers/main.coffee
+++ test/spec/controllers/main.coffee
@@ -28,6 +28,52 @@
   afterEach () ->
     @httpBackend.verifyNoOutstandingExpectation()
     @httpBackend.verifyNoOutstandingRequest()
+
+
+  # Some Mockup data:
+  #------------------
+
+  allPackages1 = [
+    { 'name': 'xx', 'versions': [
+        {'version':'1.0','id':'xx10'}
+      ]
+    },
+    { 'name': 'yy', 'versions': [
+        {'version':'1.1','id':'yy11'},
+        {'version':'1.2','id':'yy12'}
+      ]
+    }
+  ]
+
+  package1 = {
+      'name': 'accountsservice',
+      'uri': 'http://us.archive.ubuntu.com/ubuntu/pool/main/a/accountsservice/accountsservice_0.6.15-2ubuntu9_amd64.deb',
+      'summary': 'query and manipulate user account information',
+      'version': '0.6.15-2ubuntu9',
+      'architecture': 'amd64',
+      'provider': 'apt',
+      'archive': 'precise',
+      'nodes': [
+        'my1.full.fqdn'
+      ]
+    }
+
+  package2 = {
+      'name': 'otherservice',
+      'uri': 'http://us.archive.ubuntu.com/ubuntu/pool/main/o/otherservice/otherservice_0.6.15-2ubuntu9_amd64.deb',
+      'summary': 'some other service',
+      'version': '0.2-2ubuntu9',
+      'architecture': 'amd64',
+      'provider': 'apt',
+      'archive': 'precise',
+      'nodes': [
+        'my2.full.fqdn'
+      ]
+    }
+
+
+  # The tests:
+  #-----------

   it 'should have no default host configured', () ->
     expect(scope.ponyExpressHost).toBe(undefined)
@@ -133,32 +179,22 @@
     expect(n.packages[0].summary).toBe( 'query and manipulate user account information' )

   it 'should be a able to fetch /packages', () ->
-    packages = [
-      { 'name': 'xx', 'versions': [
-          {'version':'1.0','id':'xx10'}
-        ]
-      },
-      { 'name': 'yy', 'versions': [
-          {'version':'1.1','id':'yy11'},
-          {'version':'1.2','id':'yy12'}
-        ]
-      }
-    ]
-    paginateResponse @httpBackend, '/v1/packages', packages, () -> scope.fetchPackages()
-
-    expect(scope.packages.length).toBe(2)
+    ps = allPackages1
+    paginateResponse @httpBackend, '/v1/packages', ps, () -> scope.fetchPackages()
+
+    expect(scope.packages.length).toBe(ps.length)
     # test both packages
     for idx in [0,1]
-      ps = scope.packages[idx]
-      expect(@typeOf(ps)).toBe('object')
-      expect(ps.name).toBe(packages[idx].name)
-      expect(ps.versions.length).toBe(packages[idx].versions.length)
+      res_p = scope.packages[idx]
+      expect(@typeOf(res_p)).toBe('object')
+      expect(res_p.name).toBe(ps[idx].name)
+      expect(res_p.versions.length).toBe(ps[idx].versions.length)

       # every package we load creates an entry in the package map
-      for v in ps.versions
+      for v in res_p.versions
         p = scope.package[v.id]
         expect(@typeOf(p)).toBe('object')
-        expect(p.name).toBe(packages[idx].name)
+        expect(p.name).toBe(ps[idx].name)
         expect(p.version).toBe(v.version)
         expect(p.versions).toBe(undefined)

@@ -173,21 +209,9 @@
     expect(@typeOf(p)).toBe('object')
     expect(p.id).toBe(id)

-
   it 'should be able to access /package/xyz info (filled one)', () ->
     id = 'xyz'
-    r = {
-        'name': 'accountsservice',
-        'uri': 'http://us.archive.ubuntu.com/ubuntu/pool/main/a/accountsservice/accountsservice_0.6.15-2ubuntu9_amd64.deb',
-        'summary': 'query and manipulate user account information',
-        'version': '0.6.15-2ubuntu9',
-        'architecture': 'amd64',
-        'provider': 'apt',
-        'archive': 'precise',
-        'nodes': [
-          'my1.full.fqdn'
-        ]
-      }
+    r = package1
     @httpBackend.whenGET('/v1/package/'+id).respond(r)
     @httpBackend.expectGET('/v1/package/'+id)
     scope.fetchPackage(id)
@@ -204,3 +228,17 @@
     expect(p.provider).toBe(r.provider)
     expect(p.archive).toBe(r.archive)
     expect(p.nodes).toBe(r.nodes)
+
+  it 'should provide all packages if no node is selected', () ->
+    scope.allPackages = allPackages1
+    scope.updatePackageSelection()
+    expect( scope.packages ).toBe( scope.allPackages )
+
+  it 'should provide only the packages assigned to a selected node', () ->
+    scope.allPackages = allPackages1
+    scope.node['n'] = {}
+    scope.node['n'].packages = [ { 'id': allPackages1[0].versions[0].id } ]
+    scope.nodeSelected['n'] = true
+    scope.updatePackageSelection()
+    expect( scope.packages.length ).toBe( 1 )
+    expect( scope.packages[0].name ).toBe( allPackages1[0].name )


payment: remove unused code

payment: remove unused code

--- client/app/Applications/Dashboard.kdapplication/views/productsectionview.coffee
+++ client/app/Applications/Dashboard.kdapplication/views/productsectionview.coffee
@@ -1,8 +1,6 @@
 class GroupProductSectionView extends JView

   viewAppended: ->
-    group = @getData()
-
     { category, itemClass } = @getOptions()

     @setClass "payment-settings-view"


renamed selected_fact_base

renamed selected_fact_base

--- core/app/backbone/views/fact_relations/auto_complete_fact_relations_view.coffee
+++ core/app/backbone/views/fact_relations/auto_complete_fact_relations_view.coffee
@@ -1,5 +1,3 @@
-# TODO Rename selected_fact_base
-
 class window.AutoCompleteFactRelationsView extends AutoCompleteSearchView
   className: "auto-complete auto-complete-fact-relations"

@@ -38,10 +36,10 @@
     @wheel_region.show new PersistentWheelView(model: @wheel)

   addCurrent: ->
-    selected_fact_base = @_search_list_view.currentActiveModel().attributes
+    selected_fact_attributes = @_search_list_view.currentActiveModel().attributes

-    if selected_fact_base?
-      @addSelected(selected_fact_base)
+    if selected_fact_attributes?
+      @addSelected(selected_fact_attributes)
     else
       @addNew()

@@ -65,10 +63,10 @@

     mp_track "Evidence: Switching to comment"

-  addSelected: (selected_fact_base)->
+  addSelected: (selected_fact_attributes)->
     @trigger 'createFactRelation', new FactRelation
-      evidence_id: selected_fact_base.id
-      from_fact: selected_fact_base
+      evidence_id: selected_fact_attributes.id
+      from_fact: selected_fact_attributes
       created_by: currentUser.toJSON()

   setQuery: (text) -> @model.set text: text


Comment clean-up.

Comment clean-up.

--- src/element.coffee
+++ src/element.coffee
@@ -43,7 +43,6 @@
         throw new Error("Not Implemented error")

     # Apply an impulse force to the element.
-    #
     applyImpulse : (impulse) ->
         velocity = @getVelocity().add(impulse)
         @direction = velocity.normalize()


:ref in /repos/:org/:name/commits/:ref can be anything

--- src/grammar.coffee
+++ src/grammar.coffee
@@ -130,8 +130,8 @@
         | pages / builds
         | pages / builds / latest
         | commits
-        | commits / [a-f0-9]{40}
-        | commits / [a-f0-9]{40} / (
+        | commits / [^/]+
+        | commits / [^/]+ / (
               comments
             | status
             | statuses


Changing sentance structure in a grammar rule explanation

--- src/grammar.coffee
+++ src/grammar.coffee
@@ -120,7 +120,7 @@
     o 'STRING',                                 -> new Literal $1
   ]

-  # All of our immediate values. These can (in general) be passed straight
+  # All of our immediate values. Generally these can be passed straight
   # through and printed to JavaScript.
   Literal: [
     o 'AlphaNumeric'


:lipstick:

:lipstick:

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -247,14 +247,12 @@
     else String.fromCharCode(charCode)

 isASCII = (charCode) ->
-  return (
-    (charCode > 47 and charCode < 58)   or # number keys
-    (charCode is 32 or charCode is 13)  or # spacebar & return keys
-    (charCode > 64 and charCode < 91)   or # Uppercase letter keys
-    (charCode > 96 and charCode < 123)  or # Lowercase letter keys
-    (charCode > 185 and charCode < 193) or # ;=,-./`
-    (charCode > 218 and charCode < 223)    # [\]'
-  )
+  (charCode in [13, 32]) or # spacebar & return keys
+  (47  < charCode < 58)  or # number keys
+  (64  < charCode < 91)  or # Uppercase letter keys
+  (96  < charCode < 123) or # Lowercase letter keys
+  (185 < charCode < 193) or # ;=,-./`
+  (218 < charCode < 223)    # [\]'

 numpadToASCII = (charCode, shifted) ->
   trans = NumPadToASCII[charCode]


Fixed some form

Fixed some form

--- src/hydrate.coffee
+++ src/hydrate.coffee
@@ -257,10 +257,10 @@
         for num in [o.version..migrations.length - 1]
           migrations[num].call(o)
         delete o.version
-      #do actual clean
+      # do actual clean
       cleaned.push o
       if Util.isArray(o)
-        for i in o by 1
+        for i in o
           @clean(i, cleaned)
       else # o is an object
         for k, v of o


JasmineStore refactoring

JasmineStore refactoring

--- src/jasmine.coffee
+++ src/jasmine.coffee
@@ -1,13 +1,10 @@
 define 'jasmine', ->
-  Jasmine = undefined
+  Jasmine = undefined unless Jasmine?

-  ->
-    @set = (value)->
-      Jasmine = value
+  {
+    instance: do (Jasmine = Jasmine)-> Jasmine

-    @instance = Jasmine
+    set: (value)-> @instance = Jasmine = value

-    @defined = ->
-      Jasmine?
-
-    this+    defined: -> Jasmine?
+  }


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -117,7 +117,7 @@
       y: 5
     radius: 3
     showName: true
-    text: ""
+    text: 'Boss '

   # =>
   </pre></code>


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -32,7 +32,7 @@
 </pre></code>

 Metered module
-@name Mo
+@name Module
 @module
 @constructor
 @param {Object} I Instance variables


nicer debug behavior

nicer debug behavior

--- src/methods.coffee
+++ src/methods.coffee
@@ -171,7 +171,7 @@
         # dirty hack to bounce up the inheritance tree, to make sure we call the method on the most specific type
         obj = caller_stack[caller_stack.length-@param_bytes]
         unless caller_stack.length-@param_bytes >= 0 and obj?
-          error "undef'd object: (#{caller_stack})[-#{@param_bytes}] (#{sig})"
+          util.java_throw runtime_state, 'java/lang/Error', "undef'd object: (#{caller_stack})[-#{@param_bytes}] (#{sig})"
         m_spec = {class: obj.type.toClassString(), sig: @name + @raw_descriptor}
         m = runtime_state.method_lookup(m_spec)
         #throw "abstract method got called: #{@name}#{@raw_descriptor}" if m.access_flags.abstract
@@ -179,18 +179,20 @@
       params = @take_params caller_stack
       runtime_state.meta_stack.push(new runtime.StackFrame(this,params,[]))
     padding = (' ' for [2...runtime_state.meta_stack.length]).join('')
-    debug "#{padding}entering method #{sig}"
     # check for trapped and native methods, run those manually
     cf = runtime_state.curr_frame()
     if cf.resume? # we are resuming from a yield, and this was a manually run method
+      debug "#{padding}resuming method #{sig}"
       @run_manually cf.resume, runtime_state
       cf.resume = null
     else if trapped_methods[sig]
+      debug "#{padding}entering trapped method #{sig}"
       @run_manually trapped_methods[sig], runtime_state
     else if @access_flags.native
       if sig.indexOf('::registerNatives()V',1) >= 0 or sig.indexOf('::initIDs()V',1) >= 0
         @run_manually ((rs)->), runtime_state # these are all just NOPs
       else if native_methods[sig]
+        debug "#{padding}entering native method #{sig}"
         @run_manually native_methods[sig], runtime_state
       else
         try
@@ -198,8 +200,9 @@
         finally
           runtime_state.meta_stack.pop()
     else if @access_flags.abstract
-      throw "called abstract method: #{sig}"
+      util.java_throw runtime_state, 'java/lang/Error', "called abstract method: #{sig}"
     else
+      debug "#{padding}entering method #{sig}"
       @run_bytecode runtime_state, padding
     cf = runtime_state.curr_frame()
     debug "#{padding}stack: [#{pa cf.stack}], local: [#{pa cf.locals}] (method end)"


rewrite options.coffee to use helpers.coffee

--- src/options.coffee
+++ src/options.coffee
@@ -1,14 +1,8 @@
 'use strict'
-
-# helpers
-#
-$ = document.querySelector.bind document
-$$ = document.querySelectorAll.bind document
-val = (obj) -> obj.value
-last = (arr) -> arr[arr.length-1] if arr.length > 0

 K = require './keyframes.coffee'
 C = require './color_helpers.coffee'
+H = require './helpers.coffee'

 class KFTable
     constructor: (@table, @keymode) ->
@@ -102,9 +96,9 @@
         @add_button.addEventListener 'click', (event) =>
             event.preventDefault()
             @add()
-            @table.appendChild last(@views).render().row
-
-        $ '#save'
+            @table.appendChild H.last(@views).render().row
+
+        H.$ '#save'
             .addEventListener 'click', (event) ->
                 event.preventDefault()
                 chrome.runtime.sendMessage {
@@ -143,19 +137,19 @@
         chrome.runtime.sendMessage type: 'init_options', (resp) =>
             @mode = resp.mode
             @color = resp.color
-            @table = new KFTable $('#keyframes'), resp.keymode
+            @table = new KFTable H.$('#keyframes'), resp.keymode

             @table.add kf for kf in resp.kfs
             @table.create()
                 .render()

-            $ '#color'
+            H.$ '#color'
                 .value = C.rgb_to_hex resp.color

-            $ '#mode'
+            H.$ '#mode'
                 .checked = @mode is 'auto'

-            $ '#auto_opac-toggle'
+            H.$ '#auto_opac-toggle'
                 .checked = resp.auto_opac

             @toggle_slides()
@@ -163,11 +157,11 @@
         @port = chrome.runtime.connect name: 'options'
         @port.onMessage.addListener (msg) ->
             if msg.type is 'set auto_opac'
-                $ '#auto_opac-toggle'
+                H.$ '#auto_opac-toggle'
                     .checked = msg.value

         self = this
-        $ '#color'
+        H.$ '#color'
             .addEventListener 'input', (event) ->
                 event.preventDefault()
                 self.color = C.hex_to_rgb @value
@@ -180,7 +174,7 @@
                         console.log chrome.runtime.lastError

-        $ '#mode'
+        H.$ '#mode'
             .addEventListener 'click', (event) ->
                 self.mode = if @checked then 'auto' else 'manual'
                 chrome.runtime.sendMessage {
@@ -193,7 +187,7 @@
                         console.log 'ERROR when setting mode!'
                         console.log chrome.runtime.lastError

-        $ '#auto_opac-toggle'
+        H.$ '#auto_opac-toggle'
             .addEventListener 'click', (event) ->
                 chrome.runtime.sendMessage {
                     type: 'set',
@@ -203,28 +197,28 @@
                         console.log 'ERROR when setting auto_opac!!'
                         console.log chrome.runtime.lastError

-        $ '#export'
+        H.$ '#export'
           .addEventListener 'click', =>
             # show EXPORT dialog
-            $ '#dialog'
+            H.$ '#dialog'
               .style.visibility = "visible"

-            $ '#dialog-json'
+            H.$ '#dialog-json'
               .value = JSON.stringify @table.kfs

-        $ '#import'
+        H.$ '#import'
           .addEventListener 'click', =>
-            $ '#dialog'
+            H.$ '#dialog'
               .style.visibility = "visible"

-            for el in $$ '.import-dialog'
+            for el in H.$H.$ '.import-dialog'
               do -> el.style.visibility = "visible"

-        $ '#dialog-load'
+        H.$ '#dialog-load'
           .addEventListener 'click', =>
             console.log "attempting to load json!"
             try
-              kfs = JSON.parse $('#dialog-json').value
+              kfs = JSON.parse H.$('#dialog-json').value
               console.log kfs
               if kfs.length? and kfs.length > 0
                 @table.clear_kfs()
@@ -234,34 +228,34 @@
               console.log 'failed parsing imported json'
               console.log e

-        $ '#dialog-close'
+        H.$ '#dialog-close'
           .addEventListener 'click', (ev) =>
             ev.stopPropagation()
             @clear_dialog()

-        $ '#dialog'
+        H.$ '#dialog'
           .addEventListener 'click', => @clear_dialog()

-        $ '#dialog-json'
+        H.$ '#dialog-json'
           .addEventListener 'click', (ev) -> ev.stopPropagation()

     mode: 'auto',
     color: {},

     toggle_slides: ->
-        $ '#auto'
+        H.$ '#auto'
             .classList.toggle 'active', @mode is 'auto'
-        $ '#manual'
+        H.$ '#manual'
             .classList.toggle 'active', @mode is 'manual'

     clear_dialog: ->
-      $ '#dialog'
+      H.$ '#dialog'
         .style.visibility = "hidden"

-      for el in $$ '.import-dialog'
+      for el in H.$H.$ '.import-dialog'
         do -> el.style.visibility = "hidden"

-      $ '#dialog-json'
+      H.$ '#dialog-json'
         .value = ""


Cleanup scripts

Cleanup scripts

--- src/prefixr.coffee
+++ src/prefixr.coffee
@@ -69,22 +69,3 @@
         result += "#{spaces}#{vendor}#{prop}: #{value};\n"
       result
   css
-
-#if(self.functions.indexOf('linear-gradient') > -1) {
-#			// Gradients are supported with a prefix, convert angles to legacy
-#			css = css.replace(/(\s|:|,)(repeating-)?linear-gradient\(\s*(-?\d*\.?\d*)deg/ig, function ($0, delim, repeating, deg) {
-#				return delim + (repeating || '') + 'linear-gradient(' + (90-deg) + 'deg';
-#			});
-#		}
-
-## > vendoredProperties.forEach(function(prop) {
-#  var regex = new RegExp("(?:;*)([ \s\t]*)?(" + prop + ")[\s]*:([^\n;]+);?");
-#   inputCSS = inputCSS.replace(regex, function(match, spaces, prop, value) {
-#     spaces = spaces || "";
-#     var result = "";
-#     vendors.forEach(function(vendor) {
-#       result += spaces + vendor + prop + ": " + value.replace("\n", "").trim() + ";\n";
-#     });
-#     return result;
-#   });
-# });


Don't log anymore.

Don't log anymore.

--- src/project.coffee
+++ src/project.coffee
@@ -392,7 +392,6 @@
   subscribeToBuffer: (buffer) ->
     buffer.onDidDestroy => @removeBuffer(buffer)
     buffer.onDidChangePath =>
-      console.log('did change path! ' + buffer.getPath())
       unless @getPaths().length > 0
         @setPaths([path.dirname(buffer.getPath())])
     buffer.onWillThrowWatchError ({error, handle}) =>


Support scraping channel descriptions.

Support scraping channel descriptions.

--- src/scraper.coffee
+++ src/scraper.coffee
@@ -118,6 +118,9 @@
                   reject reason

           .then (html) ->
+            # Close the page and release resources.
+            page.close()
+
             $ = cheerio.load html

             res = []
@@ -143,8 +146,6 @@
                 comment.children = children
               res.push comment

-            # Clean up.
-            page.close()

             user = $(".yt-user-info a")
             resolve
@@ -162,6 +163,44 @@
             reject reason

+module.exports.channel = (id) ->
+  ###
+  Scraping a Youtube channel page and return a description of the channel.
+
+  ## Args
+  * id: channel ID.
+
+  ## Returns
+    Promise object. Use "then" method to recieve results.
+  ###
+  url = "https://www.youtube.com/channel/#{id}/about"
+  new Promise (resolve, reject) ->
+
+    phantom.get().then (ph) ->
+
+      ph.createPage().then (page) ->
+
+        page.open(url)
+          .then ->
+            page.evaluate ->
+              document.body.innerHTML
+
+          .then (html) ->
+            # Close the page and release resources.
+            page.close()
+
+            $ = cheerio.load html
+            resolve
+              id: id
+              name: $(".qualified-channel-title-text").text()
+              description: $(".about-description").text().replace(/^\s+|\s+$/g, "")
+
+          .catch (reason) ->
+            console.error reason
+            page.close()
+            reject reason
+
+
 module.exports.close = phantom.delete
 ###
 Close this module.


:lipstick:

:lipstick:

--- lib/keybinding-resolver-view.coffee
+++ lib/keybinding-resolver-view.coffee
@@ -11,10 +11,9 @@
   initialize: ({attached})->
     @attach() if attached

-    atom.workspaceView.command "keybinding-resolver:toggle", => @toggle()
+    atom.workspaceView.command 'keybinding-resolver:toggle', => @toggle()
     $(document).preempt 'keydown', (event) => @handleEvent(event)
-    @on "click", ".source", (event) ->
-      atom.workspaceView.open(event.target.innerText)
+    @on 'click', '.source', (event) -> atom.workspaceView.open(event.target.innerText)

   serialize: ->
     attached: @hasParent()


remove ';' in coffee source

remove ';' in coffee source

--- src/session.coffee
+++ src/session.coffee
@@ -1,4 +1,4 @@
-crypto = require 'crypto';
+crypto = require 'crypto'
 Blog = require './resources/blog'
 Product = require './resources/product'
 Order = require './resources/order'
@@ -58,7 +58,7 @@
     not empty(@url) and not empty(@token)

   computedPassword: ->
-    crypto.createHash('md5').update("#{@secret}#{@token}").digest("hex");
+    crypto.createHash('md5').update("#{@secret}#{@token}").digest("hex")

   prepareUrl: (url) ->
     return '' if empty(url)


:green_heart: Remove call to removeAtKeyPath

--- lib/mixins/plugin-management.coffee
+++ lib/mixins/plugin-management.coffee
@@ -69,6 +69,5 @@

   unregisterPluginControls: (name) ->
     atom.config.unobserve "minimap.plugins.#{name}"
-    atom.config.removeAtKeyPath "minimap.plugins", name
     atom.workspaceView.off "minimap:toggle-#{name}"
     delete @configDefaults.plugins[name]


App 'package.json' 'styles' object may contains paths for external styles

--- lib/tasks/build/parse/styles.coffee
+++ lib/tasks/build/parse/styles.coffee
@@ -33,6 +33,10 @@
 	for key of packageConfig.dependencies
 		if /^neft\-styles\-/.test(key)
 			inputDirs.push path: "node_modules/#{key}", prefix: "#{key}/"
+
+	if utils.isObject(packageConfig.styles)
+		for key, val of packageConfig.styles
+			inputDirs.push path: val, prefix: "#{key}/"

 	for dir, i in inputDirs then do (dir) ->
 		if dir.prefix


remove redundant if

remove redundant if

--- src/storage.coffee
+++ src/storage.coffee
@@ -55,8 +55,7 @@
             for own k, v of changes
                 do (k, v) ->
                     if H.contains k, ['alt', 'kfs', 'mode', 'keymode', 'color']
-                        if not refresh_requested
-                          refresh_requested = true
+                        refresh_requested = true
                     else if k is 'auto_opac' and v.newValue
                         chrome.runtime.sendMessage type: 'update_opacity'


multiple improvements

multiple improvements

--- src/uapanfw.coffee
+++ src/uapanfw.coffee
@@ -22,7 +22,7 @@
 sprintf = require("sprintf-js").sprintf

 modulename = 'fw'
-fwdata_file = modulename + ".json"
+data_file = modulename + ".json"
 safety_fail_note = 'If this is time critical ask a human; otherwise please open a ticket.'
 displayfmt = '%-4s %-50s %-15s %s'
 timefmt = 'YYYY-MM-DD HH:mm:ss ZZ'
@@ -56,10 +56,10 @@
 fwnames =
   '10.9.0.252': 'Fairbanks-1'
   '10.9.0.253': 'Fairbanks-2'
-  '10.9.128.252': 'Anchorage-1'
-  '10.9.128.253': 'Anchorage-2'
-  '10.9.192.252': 'Juneau-1'
-  '10.9.192.253': 'Juneau-2'
+  '10.9.128.10': 'Anchorage-1'
+  '10.9.128.11': 'Anchorage-2'
+  '10.9.192.10': 'Juneau-1'
+  '10.9.192.11': 'Juneau-2'

 if process.env.HUBOT_AUTH_ADMIN
   admins = process.env.HUBOT_AUTH_ADMIN.split ','
@@ -115,7 +115,7 @@
     usermsg = "fw: #{list_name} entries will expire soon: " +
       "```"+ expiring.join("\n") + "```"
     notifySubscribers usermsg
-    fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+    writeData()

 expireEntriesFromList = (list_name) ->
@@ -136,19 +136,19 @@
     usermsg = "fw: #{list_name} entries expired and have been removed: " +
       "```"+ deleted.join("\n") + "```"
     notifySubscribers usermsg
-    fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
-
-
-notifySubscribers = (msg, current_un = false) ->
+    writeData()
+
+
+notifySubscribers = (usermsg, current_un = false) ->
   console.error 'bad robotRef' unless robotRef
   for un in fwdata.notify
-    robotRef.send { room: un }, msg unless current_un && un == current_un
-
-
-notifyAdmins = (msg, current_un = false) ->
+    robotRef.send { room: un }, usermsg unless current_un && un == current_un
+
+
+notifyAdmins = (usermsg, current_un = false) ->
   console.error 'bad robotRef' unless robotRef
-  for un in admins
-    robotRef.send { room: un }, msg unless current_un && un == current_un
+  for un in admins when un.indexOf('U') != 0
+    robotRef.send { room: un }, usermsg unless current_un && un == current_un

 showAdmins = (robot, msg) ->
@@ -246,7 +246,7 @@
   robot.logger.info logmsg

   fwdata[list_name].push entry
-  fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+  writeData()

   usermsg = "#{who} added `#{entry.val}` to firewall #{list_name}. " +
     "Expires `#{entry.expires}`.  Change will be applied in < 5 minutes."
@@ -326,7 +326,7 @@
     "#{list_name} #{entry.type} #{entry.val} new expiration #{moment(entry.expires).format(timefmt)}"
   robot.logger.info logmsg

-  fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+  writeData()

   usermsg = "#{who} updated expiration for `#{entry.val}` #{list_name}ing. " +
     "New expiration `#{entry.expires}`."
@@ -386,7 +386,7 @@
       "Change will be applied in < 5 minutes. Removed: " +
       "```"+ deleted.join("\n") + "```"
     fwdata[list_name] = new_entry
-    fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+    writeData()
   else
     usermsg = "#{list_name} delete request did not match any records."
   msg.reply usermsg
@@ -449,7 +449,7 @@
     "added #{who} to firewall change notifications"
   robot.logger.info logmsg

-  fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+  writeData()

 unsubscribe = (robot, msg) ->
@@ -470,7 +470,7 @@
     "removed #{who} from firewall change notifications"
   robot.logger.info logmsg

-  fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+  writeData()

 showSubscribers = (robot, msg) ->
@@ -532,7 +532,7 @@
   for obj in fwdata.firewalls
     if obj.ip is clientip and obj.type is l_type and obj.list is list_name
       obj.checkin = moment().add(5,'minutes')
-      fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+      writeData()
       return
   # otherwise create new object
   obj =
@@ -545,7 +545,14 @@
   if fwdata.firewalls.length > 1
     fwdata.firewalls = fwdata.firewalls.sort (a,b) ->
       sortBy('name',a,b) or sortBy('list',a,b) or sortBy('type',a,b)
-  fs.writeFileSync fwdata_file, JSON.stringify(fwdata), 'utf-8'
+  writeData()
+
+
+writeData = ->
+  fs.writeFileSync data_file, JSON.stringify(fwdata), 'utf-8'
+  logmsg = "#{modulename}: wrote #{data_file}"
+  robotRef.logger.info logmsg
+

 module.exports = (robot) ->

@@ -553,9 +560,11 @@
   setTimeout expirationWorker, svcQueueIntervalMs

   try
-    fwdata = JSON.parse fs.readFileSync fwdata_file, 'utf-8'
+    fwdata = JSON.parse fs.readFileSync data_file, 'utf-8'
+    robot.logger.info "#{modulename}: read #{data_file}" if robot.logger
   catch error
-    console.log('Unable to read file', error) unless error.code is 'ENOENT'
+    unless error.code is 'ENOENT'
+      console.log("#{modulename}: unable to read #{data_file}: ", error)

   robot.router.get "/#{robot.name}/#{modulename}/blacklist/url", (req, res) ->
     return httpGetList robot, req, res, 'blacklist', 'url'
@@ -570,6 +579,7 @@
     return httpGetList robot, req, res, 'whitelist', 'cidr'

   robot.respond /(?:firewall|fw)(?: help| h|)$/, (msg) ->
+    who = msg.envelope.user.name
     cmds = ['```']
     arr = [
       modulename + " show (white|black)list [searchterm]"
@@ -589,7 +599,7 @@

     msg.reply cmds.join "\n"

-    logmsg = "#{modulename}: robot responded to #{msg.envelope.user.name}: " +
+    logmsg = "#{modulename}: robot responded to #{who}: " +
       "displayed #{modulename} help"
     robot.logger.info logmsg


Activity: prefetched data key navigatedData changed to navigated

--- workers/social/lib/social/cache/socialapi.coffee
+++ workers/social/lib/social/cache/socialapi.coffee
@@ -77,7 +77,7 @@
         slug:    params?.slug    or "/"
         data:    data

-      queue.localPrefetchedFeeds.navigatedData = res
+      queue.localPrefetchedFeeds.navigated = res
       queue.fin()

   dash queue, ()-> callback null, queue.localPrefetchedFeeds


KiteSubscription: remove kiteplan and use jpaymentplan instead.

--- workers/social/lib/social/models/kiteplan.coffee
+++ workers/social/lib/social/models/kiteplan.coffee
@@ -1,100 +0,0 @@
-jraphical = require 'jraphical'
-module.exports = class JKitePlan extends jraphical.Module
-  {permit}            = require './group/permissionset'
-  {secure, signature} = require 'bongo'
-  KodingError         = require '../error'
-  JKite               = require './kite'
-  {Relationship}      = jraphical
-
-  @share()
-  @set
-    permissions           :
-      'list kite plans'   : ['member']
-      'create kite plans' : ['member']
-    schema                :
-      name                : String
-      description         : String
-      price               : String
-      recurring           : String
-      createdAt           :
-        type              : Date
-        default           : -> new Date
-    sharedEvents          :
-      instance            : []
-      static              : []
-    sharedMethods         :
-      static:
-        list:
-          (signature Object, Object, Function)
-        create:
-          (signature Object, Function)
-      instance :
-        modify :
-          (signature Object, Function)
-
-  @create: permit 'create kite plans',
-    success:(client, formData, callback)->
-      account  = client.connection.delegate
-      {kiteId} = formData
-
-      Relationship.one {
-        targetName  : "JKite"
-        targetId    : kiteId
-        sourceName  : "JAccount"
-        sourceId    : account.getId()
-        as          : "owner"
-      }, (err, rel) =>
-        return  callback new KodingError err if err or not rel
-        rel.fetchTarget (err, kite) =>
-          kitePlan = new JKitePlan formData
-          kitePlan.save (err)->
-            return  callback new KodingError err if err
-            kite.addPlan kitePlan, (err, res)->
-              return  callback new KodingError err if err
-              callback null, kitePlan
-
-  modify: permit 'edit kite plan',
-    success:(client, formData, callback)->
-      {kite} = formData
-      Relationship.one {
-        targetName  : "JKite"
-        targetId    : kite._id
-        sourceName  : "JAccount"
-        sourceId    : account.getId()
-        as          : "owner"
-      }, (err, rel) ->
-        return  callback new KodingError err if err or not rel
-        updatedFields =
-          name        : formData.name
-          price       : formData.price
-          description : formData.description
-          recurring   : formData.recurring
-
-        @update $set: updatedFields , callback
-
-  deletePlan: permit 'delete kite plan',
-    success:(client, callback)->
-      Relationship.one {
-        targeName   : "JKite"
-        targetId    : @getId()
-        sourceName  : "JAccount"
-        sourceId    : account.getId()
-        as          : "owner"
-      }, (err, rel) =>
-        return  callback new KodingError err if err
-        @remove (err, res)->
-          return  callback err, res
-
-  # we may change this method after implementing
-  # recurly calls for each subscription.
-  fetchPlanSubscriptions: permit 'fetch plans',
-    success:(client, callback)->
-      Relationship.some {
-        targeName   : "JKitePlan"
-        targetId    : @getId()
-        sourceName  : "JAccount"
-        as          : "kiteSubscription"
-      }, callback
-
-
-


Don't overwrite updates variable

Don't overwrite updates variable

--- src/upgrade.coffee
+++ src/upgrade.coffee
@@ -133,10 +133,10 @@
       return callback(error) if error?

       if options.argv.json
-        updates = updates.map ({pack, latestVersion}) ->
+        packagesWithLatestVersion = updates.map ({pack, latestVersion}) ->
           pack.latestVersion = latestVersion
           pack
-        console.log JSON.stringify(updates)
+        console.log JSON.stringify(packagesWithLatestVersion)
       else
         console.log "Package Updates Available".cyan + " (#{updates.length})"
         tree updates, ({pack, latestVersion}) ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/flickerable.coffee
+++ test/flickerable.coffee
@@ -26,7 +26,7 @@

   5.times (n) ->
     player.update()
-
+    equals player.I.alpha, 0.

   player.update()
   equals player.I.alpha, 0.2


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/flickerable.coffee
+++ test/flickerable.coffee
@@ -11,5 +11,6 @@
   player.flicker
     duration:
     frequency:
+

 module()


sized sprites properly

sized sprites properly

--- web/src/cs/views/default.coffee
+++ web/src/cs/views/default.coffee
@@ -15,6 +15,18 @@
 		#scene.add(imageMesh)
 		sp = new THREE.Sprite(material)
 		sp.position.set(0, index ,0)
+
+		size = 1
+		imageDimensions = {w: image.texture.image.width, h: image.texture.image.height}
+		ratio = imageDimensions.w / imageDimensions.h
+		spriteDimensions = {}
+		if imageDimensions.w > imageDimensions.h
+			spriteDimensions.w = size
+			spriteDimensions.h = (1 / ratio) * size
+		else
+			spriteDimensions.h = size
+			spriteDimensions.w = ratio * size
+		sp.scale.set(spriteDimensions.w,spriteDimensions.h,0)
 		scene.add(sp)
 	)


switch from mongoose to mongojs in ClsiManager

for efficiency

--- services/web/app/coffee/Features/Compile/ClsiManager.coffee
+++ services/web/app/coffee/Features/Compile/ClsiManager.coffee
@@ -3,6 +3,7 @@
 Settings = require "settings-sharelatex"
 request = require('request')
 Project = require("../../models/Project").Project
+ProjectGetter = require("../Project/ProjectGetter")
 ProjectEntityHandler = require("../Project/ProjectEntityHandler")
 logger = require "logger-sharelatex"
 Url = require("url")
@@ -120,7 +121,7 @@
 	VALID_COMPILERS: ["pdflatex", "latex", "xelatex", "lualatex"]

 	_buildRequest: (project_id, options={}, callback = (error, request) ->) ->
-		Project.findById project_id, {compiler: 1, rootDoc_id: 1, imageName: 1, rootFolder:1}, (error, project) ->
+		ProjectGetter.getProject project_id, {compiler: 1, rootDoc_id: 1, imageName: 1, rootFolder:1}, (error, project) ->
 			return callback(error) if error?
 			return callback(new Errors.NotFoundError("project does not exist: #{project_id}")) if !project?
 			console.log "PROJECT", project, JSON.stringify(project.rootFolder,null,2)


spec: add help require function

spec: add help require function

to load corresponding module being loaded

--- test/spec_helper.coffee
+++ test/spec_helper.coffee
@@ -4,6 +4,10 @@
 global.assert = chai.assert
 root = path.normalize(path.join(__dirname,"..")) + "/"

-test = root + "test/"
+TESTROOT = root + "test/"
 global.SRC = root + "src/"
-global.FIXTURES = test + "fixtures"
+# global.FIXTURES = test + "fixtures"
+
+global.require_test = (file) ->
+  module_path = file.replace(TESTROOT,"")
+  require path.join(SRC,module_path)


moar commit tests.

moar commit tests.

--- test/test.commit.coffee
+++ test/test.commit.coffee
@@ -19,7 +19,27 @@
 					commit.should.be.an.instanceof gitteh.Commit
 					done()
 	describe "The first project commit...", ->
-		it "has correct oid", ->
-			commit.id.should.be.equal "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14"
-		it "has correct tree id", ->
-			commit.treeId.should.be.equal "753b8f0db281c50b692ff0f94cd2a614cfdd41b6"+		describe "#id", ->
+			it "is correct", ->
+				commit.id.should.be.equal "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14"
+			it "is immutable", ->
+				commit.id = "foo"
+				commit.id.should.be.equal "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14"
+				delete commit.id
+				commit.id.should.be.equal "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14"
+		describe "#treeId", ->
+			it "is correct", ->
+				commit.treeId.should.be.equal "753b8f0db281c50b692ff0f94cd2a614cfdd41b6"
+			it "is immutable", ->
+				commit.treeId = "foo"
+				commit.treeId.should.be.equal "753b8f0db281c50b692ff0f94cd2a614cfdd41b6"
+				delete commit.treeId
+				commit.treeId.should.be.equal "753b8f0db281c50b692ff0f94cd2a614cfdd41b6"
+		describe "#message", ->
+			it "is correct", ->
+				commit.message.should.be.equal "Initial commit."
+			it "is immutable", ->
+				commit.message = "foo"
+				commit.message.should.be.equal "Initial commit."
+				delete commit.message
+				commit.message.should.be.equal "Initial commit."


Refactor wrapper append method.

Refactor wrapper append method.

--- src/wrapper.coffee
+++ src/wrapper.coffee
@@ -22,11 +22,11 @@
       @append acorn.parse fs.readFileSync @prelude

   # can be passed an ast or module instance
-  append: (module) ->
-    if (isModule = module instanceof Module)
-      ast = module.ast
+  append: (mod) ->
+    if (isModule = mod instanceof Module)
+      ast = mod.ast
     else
-      ast = module
+      ast = mod

     if ast.body?
       for node in ast.body
@@ -35,13 +35,19 @@
     if isModule
       # append all dependencies as well
       seen = {}
-      dependencies = (v for k, v of module.dependencies)
-      while (dependency = dependencies.shift())?
-        unless dependency.async or dependency.excluded
-          @append dependency.ast
-          for k, v of dependency.dependencies
-            unless seen[v]?
-              dependencies.push seen[k] = v
+      deps = []
+
+      for k,v of mod.dependencies
+        seen[k] = true
+        deps.push v
+
+      while (dep = deps.shift())?
+        unless dep.async or dep.excluded
+          @append dep.ast
+          for k, v of dep.dependencies
+            unless seen[k]?
+              seen[k] = true
+              deps.push v

   toString: (options) ->
     codegen @ast, options


fix function parameter parsing

fix function parameter parsing

seems like the parsing engine doesn't properly backtrack as it's
written; this form is also correct and does work

--- grammar.coffee
+++ grammar.coffee
@@ -198,8 +198,10 @@
     signature: -> seq(@parameters, optional(@result))
     result: -> choice(@parameters, @type)
     parameters: -> seq("(", optional(seq(@parameter_list, optional(","))), ")")
-    parameter_list: -> seq(@parameter_decl, repeat(seq(",", @parameter_decl)))
-    parameter_decl: -> seq(optional(@identifier_list), optional("..."), @type)
+    parameter_list: -> choice(
+      seq(@nameless_parameter_decl, repeat(seq(",", @nameless_parameter_decl))))
+    named_parameter_decl: -> seq(@identifier_list, optional("..."), @type)
+    nameless_parameter_decl: -> seq(optional("..."), @type)

     interface_type: -> seq(keyword("interface"), "{", repeat(seq(@method_spec, terminator())), "}")
     method_spec: -> choice(seq(@method_name, @signature), @interface_type_name)


Fix JSON serialization for HTTPie

Fix JSON serialization for HTTPie

--- HTTPieCodeGenerator.coffee
+++ HTTPieCodeGenerator.coffee
@@ -45,7 +45,7 @@

     @body = (request) ->
         json_body = request.jsonBody
-        if json_body
+        if json_body and not json_body.length
             return {
                 "has_form_encoded":false
                 "has_json_encoded":true
@@ -96,7 +96,7 @@
                 }

     @json_body_object = (object) ->
-        if object == null
+        if object == null or !object or typeof(object) == 'undefined'
             s = "null"
         else if typeof(object) == 'string'
             s = "\"#{addslashes object}\""
@@ -104,58 +104,21 @@
             s = "#{object}"
         else if typeof(object) == 'boolean'
             s = "#{if object then "true" else "false"}"
-        else if typeof(object) == 'object'
+        else
             if object.length?
-                s = "'[" + ("#{@json_body_object(value)}" for value in object).join(',') + "]'"
+                s = "    \"#{ addslashes(JSON.stringify(object)) }\""
             else
                 s = ""
                 for key, value of object
-                    sign = "#{if typeof(value) == 'string' then "=" else ":="}"
-                    if typeof value == 'object'
-                      s += addslashes(key) + sign
-                      if value.length != null
-                        s += @nested_array_object(value, 1)
+                    if s.length > 0
+                        s += ' \\\n'
+                    if typeof(value) == 'string'
+                        s += "    #{ addslashes(key) }=\"#{ addslashes(value) }\""
+                    else if typeof(value) == 'object' and value != null
+                        s += "    #{ addslashes(key) }:=\"#{ addslashes(JSON.stringify(value, null, '  ')) }\""
                     else
-                      s += '\'{\n' + @nested_hash_object(value, 1) + '}\''
+                        s += "    #{ addslashes(key) }:=#{ addslashes(value) }"
         return s
-
-    @nested_array_object = (array, level) ->
-      s = '['
-      for index of array
-        value = array[index]
-        indentationString = '  '.repeat(level - 1)
-        if typeof value == 'object'
-          if value.length != null
-            s += @nested_array_object(value, level)
-          else
-            s += '{\n' + @nested_hash_object(value, level) + indentationString + '}'
-        else
-          s += @json_body_object(value)
-        if index < array.length - 1
-          s += ', '
-      s += ']'
-      s
-
-    @nested_hash_object = (object, level) ->
-      s = ''
-      keys = Object.keys(object)
-      for index of keys
-        key = keys[index]
-        value = object[key]
-        indentationString = '  '.repeat(level)
-        s += indentationString
-        s += '"' + addslashes(key) + '": '
-        if typeof value == 'object'
-          if value.length != null
-            s += @nested_array_object(value, level + 1)
-          else
-            s += '{\n' + @nested_hash_object(value, level + 1) + indentationString + '}'
-        else
-          s += @json_body_object(value)
-        if index < keys.length - 1
-          s += ', '
-        s += ' \n'
-      s

     @strip_last_backslash = (string) ->
         # Remove the last backslash on the last non-empty line


feat(body): Add platform as class to body

--- modules/directives/body/body.coffee
+++ modules/directives/body/body.coffee
@@ -9,5 +9,6 @@
   restrict: 'E'
   link: (scope, element, attrs) ->
     scope.platform = attrs.platform or 'ios'
+    element.addClass scope.platform

 angular.module('bp.directives').directive 'body', body


fix for IE styling

fix for IE styling

Former-commit-id: 65901d9957bfd8a8770076ce0b2007fe8ffe0202 [formerly eac95e8f3ab69caf6c12b863f0445429ed045eac] [formerly 1176a402cbfed912a6a7a20a88f689e08b020c2c [formerly 588ae15bd5dc5c97a599662935da24baf75da33b]] [formerly caf3e38c1ae72ade08f2060b030effee4aa09ece [formerly 716867021e4ba843089daa8df8d83f1aca75d091] [formerly a5975373d9f9ba60655ab4260d06d5503ca87d14 [formerly a5975373d9f9ba60655ab4260d06d5503ca87d14 [formerly 3e8e1c998048ebcc82c5451f5f908164e4e80813]]]]
Former-commit-id: 2ff2c31674fae78c6f03556ffdaf787ac57eef53 [formerly 5f73e257cdcc5b192a0e3e663a875d2ad4196566] [formerly 1ed3cb47b1cdfe0e7687fbd01113e0b9f59ddc20 [formerly dd961ed8c36c9621a88f86cfe3be6df2599d1986]]
Former-commit-id: 3eb31f8d051d9c38021ace584b116c8fbe85fd9c [formerly 02e989796ca05ef42b39564a6e967c1fd51648c2]
Former-commit-id: d0bcc73bc712b7b7334df3764685260458e9cb34
Former-commit-id: 7c3b8c0cdaf5a57f15a00709503a0d664d84501a

--- @client/bootstrap_loader.coffee
+++ @client/bootstrap_loader.coffee
@@ -23,10 +23,11 @@
     throw "Application not defined"

   # Add defined styles
+
   style = document.createElement('style')
   style.type = 'text/css'
   if style.styleSheet
-    style.styleSheet.cssText = css
+    style.styleSheet.cssText = window.styles
   else
     style.appendChild document.createTextNode(window.styles)


clean up

clean up

--- spec/lib/router2-spec.coffee
+++ spec/lib/router2-spec.coffee
@@ -26,9 +26,7 @@
       Given -> @msg = Message()
       Given -> @end = jasmine.createSpy()
       When -> @router.route @msg, @end
-      Then ->
-        expect(@end).toHaveBeenCalledWith null, jasmine.any(Controller)
-        console.log @end
+      Then -> expect(@end).toHaveBeenCalledWith null, jasmine.any(Controller)
       And -> expect(@end.mostRecentCall.args[0]).toBe null
       And -> expect(@end.mostRecentCall.args[1].message).toBe @msg

@@ -38,9 +36,7 @@
       Given -> @sock = new EventEmitter()
       Given -> @end = jasmine.createSpy()
       When -> @router.route @msg, @sock, @end
-      Then ->
-        expect(@end).toHaveBeenCalledWith null, jasmine.any(Controller), @sock
-        console.log @end
+      Then -> expect(@end).toHaveBeenCalledWith null, jasmine.any(Controller), @sock
       And -> expect(@end.mostRecentCall.args[0]).toBe null
       And -> expect(@end.mostRecentCall.args[1].message).toBe @msg
       And -> expect(@end.mostRecentCall.args[2]).toBe @sock


:fire: spec for elixir function

:fire: spec for elixir function

--- spec/text-object-spec.coffee
+++ spec/text-object-spec.coffee
@@ -1423,54 +1423,6 @@
         it 'select function', ->
           ensure 'v a f', selectedBufferRange: [[2, 0], [7, 0]]

-    describe 'elixir', ->
-      pack = 'language-elixir'
-      scope = 'source.elixir'
-      beforeEach ->
-        console.log "ELIXIR"
-        waitsForPromise ->
-          atom.packages.activatePackage(pack)
-        set
-          text: """
-            # Commment
-
-            def hello do
-              a = 1
-              b = 2
-              c = 3
-            end
-
-            def one_liner, do: "return value"
-
-            # Commment
-            """
-          cursor: [3, 0]
-        runs ->
-          grammar = atom.grammars.grammarForScopeName(scope)
-          editor.setGrammar(grammar)
-      afterEach ->
-        atom.packages.deactivatePackage(pack)
-
-      describe 'inner-function for elixir', ->
-        it 'select except start row', ->
-          ensure 'v i f', selectedBufferRange: [[3, 0], [6, 0]]
-      describe 'a-function for elixir', ->
-        it 'select function', ->
-          ensure 'v a f', selectedBufferRange: [[2, 0], [7, 0]]
-      describe 'one-liner for elixir', ->
-        beforeEach ->
-          set
-            text: """
-              # Commment
-
-              def one_liner, do: "return value"
-
-              # Commment
-              """
-            cursor: [3, 0]
-        it 'select function', ->
-          ensure 'v a f', selectedBufferRange: [[3, 0], [4, 0]]
-
     describe 'go', ->
       pack = 'language-go'
       scope = 'source.go'


<debug> Another day saved by Fat Arrow, the closure hero.

--- server/models/sensor.coffee
+++ server/models/sensor.coffee
@@ -54,11 +54,11 @@
 			driverId: @driverId
 		superUpdateAttributes = (data, callback) => super data, callback
 		# Update DB:
-		superUpdateAttributes data, (err, sensor) ->
-			if err
-				callback err, sensor
-			# Update Driver:
-			else
+		superUpdateAttributes data, (err, sensor) =>
+			return callback err, sensor if err
+
+			if @customId isnt prevData.customId
+				# Update Driver:
 				sensorsDrivers[@driverId].update prevData.customId, data.customId, (err2) ->
 					if err2
 						# Cancelling Modif:
@@ -69,6 +69,8 @@
 							callback err2, sensor2
 					else
 						callback null, sensor
+			else
+				callback null, sensor

 	###


support more http verb

support more http verb

--- lib/application.coffee
+++ lib/application.coffee
@@ -32,7 +32,7 @@

   exports.use.apply @, [layer].concat args

-['GET', 'POST', 'HEAD', 'OPTIONS'].forEach (method) ->
+['GET', 'POST', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'PATCH'].forEach (method) ->
   exports[method.toLowerCase()] = ->
     param = [method].concat _.toArray arguments
     exports.useMethod.apply @, param


Fixed missing bracket, found while testing #410

--- app/assets/javascripts/cleantheme/surveyAnimation.js.coffee
+++ app/assets/javascripts/cleantheme/surveyAnimation.js.coffee
@@ -133,7 +133,7 @@
     else
       assignQuestionDirect($(this).closest('.survey-container'))

-  $("[data-object~='checkbox-label'").click (event) ->
+  $("[data-object~='checkbox-label']").click (event) ->
     event.preventDefault()
     event.stopPropagation()
     checkbox = $(this).siblings('input:checkbox')


pjax: going home to a path not just /

pjax: going home to a path not just /

--- app/_src/pjaxnavigation.coffee
+++ app/_src/pjaxnavigation.coffee
@@ -51,10 +51,11 @@
     unless @currentPageId is @HOMEPAGE_ID
       @calculateY() # might not have been done before if ladning on subpage
       @showHero()
+      url = $(e.currentTarget).attr('href')
       @slideOutContent( =>
         unless popState
           # tell pjax to nav to home page
-          $.pjax({url: '/', container: @contentSelector, fragment: @contentSelector})
+          $.pjax({url: url, container: @contentSelector, fragment: @contentSelector})
       )


improved UX for user control screen

improved UX for user control screen

--- app/angular/controllers.coffee
+++ app/angular/controllers.coffee
@@ -22,7 +22,8 @@
 		aircraftControls.speed = data.speed
 		$location.path "/controls"

-app.controller 'UserControlsCtrl', ($scope, $timeout, $window, ctrlSocket, aircraftControls) ->
+app.controller 'UserControlsCtrl', ($scope, $timeout, $window, $location, ctrlSocket, aircraftControls) ->
+	$location.path("/splash") unless aircraftControls.code?
 	curX = 0
 	curY = 0
 	arrow = angular.element document.getElementById('arrow')


added stable timestamp as a property on synchronizer

--- assets/scripts/coffee/leonidas/commands/synchronizer.coffee
+++ assets/scripts/coffee/leonidas/commands/synchronizer.coffee
@@ -5,6 +5,7 @@
 class Synchronizer

 	constructor: (@syncUrl, @client, @organizer, @stabilizer)->
+		@stableTimestamp = 0
 		@externalClients = [ ]

 	push: =>
@@ -15,6 +16,7 @@
 			method: "post"
 			data:
 				clientId: @client.id
+				clients: @externalClients
 				commands: (command.toHash() for command in unsyncedCommands)
 			error: => console.log "push error"
 			success: (response)=>
@@ -32,9 +34,10 @@
 			error: => console.log "pull error"
 			success: (response)=>
 				@externalClients = response.data.currentClients
+				@stableTimestamp = response.data.stableTimestamp
 				commands = (new Command(command.name, command.data, command.connection, new Date(command.timestamp)) for command in response.data.commands)
 				@organizer.addCommands commands, false
-				@stabilizer.stabilize response.data.stableTimestamp
+				@stabilizer.stabilize @stableTimestamp
 		)

 return Synchronizer


cleanup

cleanup

remove unnecessary comments, whitespace and unused modules

--- app/coffee/MongoManager.coffee
+++ app/coffee/MongoManager.coffee
@@ -1,10 +1,8 @@
 {db, ObjectId} = require "./mongojs"
 PackManager = require "./PackManager"
 async = require "async"
-_ = require "underscore"

 module.exports = MongoManager =
-	# only used in this module
 	getLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
 		db.docHistory
 			.find(doc_id: ObjectId(doc_id.toString()))
@@ -15,11 +13,9 @@
 				return callback null, null if compressedUpdates[0]?.pack? # cannot pop from a pack
 				return callback null, compressedUpdates[0] or null

-	# only used in this module
 	deleteCompressedUpdate: (id, callback = (error) ->) ->
 		db.docHistory.remove({ _id: ObjectId(id.toString()) }, callback)

-	# used in UpdatesManager
 	popLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
 		MongoManager.getLastCompressedUpdate doc_id, (error, update) ->
 			return callback(error) if error?
@@ -30,7 +26,6 @@
 			else
 				callback null, null

-	# used in UpdatesManager
 	insertCompressedUpdates: (project_id, doc_id, updates, permanent, callback = (error) ->) ->
 		jobs = []
 		for update in updates
@@ -65,7 +60,7 @@
 			query["v"] ||= {}
 			query["v"]["$lte"] = options.to

-		PackManager.findDocResults(db.docHistory, query, options.limit, callback)
+		PackManager.findDocResults(db.docHistory, query, options.limit, callback)

 	getProjectUpdates: (project_id, options = {}, callback = (error, updates) ->) ->
 		query =
@@ -74,7 +69,7 @@
 		if options.before?
 			query["meta.end_ts"] = { $lt: options.before }

-		PackManager.findProjectResults(db.docHistory, query, options.limit, callback)
+		PackManager.findProjectResults(db.docHistory, query, options.limit, callback)

 	backportProjectId: (project_id, doc_id, callback = (error) ->) ->
 		db.docHistory.update {
@@ -103,12 +98,12 @@
 		}, callback

 	ensureIndices: () ->
-		# For finding all updates that go into a diff for a doc  (getLastCompressedUpdate, getDocUpdates v > from && v < to)
+		# For finding all updates that go into a diff for a doc
 		db.docHistory.ensureIndex { doc_id: 1, v: 1 }, { background: true }
-		# For finding all updates that affect a project (getProjectUpdates meta.end_ts < before
+		# For finding all updates that affect a project
 		db.docHistory.ensureIndex { project_id: 1, "meta.end_ts": 1 }, { background: true }
 		# For finding all packs that affect a project (use a sparse index so only packs are included)
-		db.docHistory.ensureIndex { project_id: 1, "pack.0.meta.end_ts": 1, "meta.end_ts": 1}	, { background: true, sparse: true }
+		db.docHistory.ensureIndex { project_id: 1, "pack.0.meta.end_ts": 1, "meta.end_ts": 1}, { background: true, sparse: true }
 		# For finding updates that don't yet have a project_id and need it inserting
 		db.docHistory.ensureIndex { doc_id: 1, project_id: 1 }, { background: true }
 		# For finding project meta-data


fix bug, jsonOps is array not string

fix bug, jsonOps is array not string

--- app/coffee/RedisManager.coffee
+++ app/coffee/RedisManager.coffee
@@ -162,10 +162,11 @@
 				return callback(error)

 			jsonOps = appliedOps.map (op) -> JSON.stringify op
-			if jsonOps.indexOf("\u0000") != -1
-				error = new Error("null bytes found in jsonOps")
-				logger.error err: error, doc_id: doc_id, jsonOps: jsonOps, error.message
-				return callback(error)
+			for op in jsonOps
+				if op.indexOf("\u0000") != -1
+					error = new Error("null bytes found in jsonOps")
+					logger.error err: error, doc_id: doc_id, jsonOps: jsonOps, error.message
+					return callback(error)

 			newDocLines = JSON.stringify(docLines)
 			if newDocLines.indexOf("\u0000") != -1


fix taiga-theme load twice

fix taiga-theme load twice

--- app/coffee/modules/auth.coffee
+++ app/coffee/modules/auth.coffee
@@ -43,6 +43,9 @@
     constructor: (@rootscope, @storage, @model, @rs, @http, @urls, @config, @translate, @currentUserService,
                   @themeService) ->
         super()
+
+        @._currentTheme = @config.get("defaultTheme") || "taiga" # load on index.jade
+
         userModel = @.getUser()
         @.setUserdata(userModel)

@@ -53,9 +56,15 @@
         else
             @.userData = null

+    _getUserTheme: ->
+        return @rootscope.user?.theme || @config.get("defaultTheme") || "taiga"
+
     _setTheme: ->
-        theme = @rootscope.user?.theme || @config.get("defaultTheme") || "taiga"
-        @themeService.use(theme)
+        newTheme = @._getUserTheme()
+
+        if @._currentTheme != newTheme
+            @._currentTheme = newTheme
+            @themeService.use(@._currentTheme)

     _setLocales: ->
         lang = @rootscope.user?.lang || @config.get("defaultLanguage") || "en"
@@ -71,7 +80,9 @@
             user = @model.make_model("users", userData)
             @rootscope.user = user
             @._setLocales()
+
             @._setTheme()
+
             return user

         return null


Remove debugging logging

Remove debugging logging

--- lib/drive/drive.coffee
+++ lib/drive/drive.coffee
@@ -12,9 +12,7 @@
 exports.rescanDrives = (callback) ->
 	return callback() if not IS_WINDOWS
 	diskpartRescanScriptPath = path.join(__dirname, 'scripts', 'diskpart_rescan')
-	childProcess.exec "diskpart /s \"#{diskpartRescanScriptPath}\"", {}, (error) ->
-		console.log("DISKPART RESULT: #{arguments}")
-		return callback(error)
+	childProcess.exec("diskpart /s \"#{diskpartRescanScriptPath}\"", {}, _.unary(callback))

 exports.eraseMBR = (devicePath, callback) ->
 	return callback() if not IS_WINDOWS


Slight refactoring of finger tree code.

Slight refactoring of finger tree code.

--- lib/finger_tree.coffee
+++ lib/finger_tree.coffee
@@ -19,13 +19,12 @@
   before: (x) -> if x == undefined then @ else new @constructor @data.before x
   concat: (t) -> if not t? then this else new @constructor @data.concat t.data
   reverse: -> new @constructor @data.reverse()
-  plus: (x) -> @before x
+  @::plus = @::before

 class FingerTreeType
   constructor: (measure, extensions = DefaultExtensions) ->
-    @build = ->
-      Sequence.reduce arguments, new Instance(Empty), (s, a) -> s.plus a
+    @build = -> Sequence.reduce arguments, empty, (s, a) -> s.plus a

     single = (x) -> if x == Empty or x.constructor in internal
         x.measure()
@@ -42,7 +41,7 @@
     class Instance extends extensions
       constructor: (@data) ->

-      empty: -> new Instance Empty
+      empty: -> empty

       isEmpty: -> @data.isEmpty()

@@ -225,6 +224,8 @@

       reverse: -> this
     }
+
+    empty = new Instance Empty

     # A finger tree with a single element.
@@ -439,7 +440,8 @@

   intersect: (other) -> resolve intersect @empty(), this, other

-  plus: (x) -> @insert x
+  @::plus = @::insert
+

 SortedSeq = new FingerTreeType OrderMeasure, SortedExtensions (a, b) -> a < b


Update zh-HANS.coffee (#5736)

Update zh-HANS.coffee (#5736)

--- app/locale/zh-HANS.coco.coffee
+++ app/locale/zh-HANS.coco.coffee
@@ -1,9 +1,9 @@
 module.exports = nativeDescription: "简体中文", englishDescription: "Chinese (Simplified)", translation:

   new_home:
-    title: "CodeCombat - 硅谷原创AP官方权威认证青少年编程平台"
-    meta_keywords: "青少年编程, 少儿编程, CodeCombat, CodeCombat中国, steam教育, python, javascript, 游戏化编程, 美国AP/CSP认证, AI世青赛技术支持平台"
-    meta_description: "CodeCombat中国官方教学版，美国大学理事会认证，国际等级证书，AI世青赛全球独家技术伙伴。"
+    title: "CodeCombat官方｜信息学奥赛｜AI世青赛｜编程等级认证"
+    meta_keywords: "青少年编程, 少儿编程, CodeCombat, CodeCombat中国, steam教育, python, javascript, 游戏化编程, 美国AP/CSP认证,AI世青赛,信息学奥赛"
+    meta_description: "CodeCombat中国唯一官方网站，支持Python, C++, JavaScript, 美国大学理事会（AP)认证，AI世青赛全球独家技术平台，支持中美信息学奥赛(NOI, CSP-J/S, USACO)、电子学会考试和国际青少年编程认证。"
     meta_og_url: "https://koudashijie.com"
     built_for_teachers_title: "一个以教师为中心的课程体系"
     built_for_teachers_blurb: "教孩子们写代码往往会觉得无从下手。 CodeCombat 旨在帮助所有的教育工作者传授学生学习和掌握当下最流行的两种计算机语言，JavaScript 和 Python。整个体系包含六门计算机科学课程，以及通过基于项目的游戏开发和网页开发单元巩固学习，教会孩子们一步步从基本语法到高级递归前进！"


location

location

--- app/models/found_friend.coffee
+++ app/models/found_friend.coffee
@@ -65,4 +65,14 @@
 #    else
 #      new @(objects)

+  @fetch: ->
+    navigator.geolocation.getCurrentPosition((location) =>
+      location.created_at = new Date()
+      Spine.Ajax.defaults.headers['X-Location'] = [location.coords.latitude, location.coords.longitude, location.coords.accuracy].join(',')
+      super
+      console.log 'Retrieved location', location
+    , ((error) ->
+      console.log 'Could not get location'
+    ))
+
 module.exports = FoundFriend


delete comment

delete comment

--- app/scripts/controllers.coffee
+++ app/scripts/controllers.coffee
@@ -236,7 +236,6 @@
       isvideo: false
       iframe: true
       original: url
-    # embed video youtube
     image.medium_url= $sce.trustAsResourceUrl(url)
     Lightbox.one_media = true
     Lightbox.openModal([image], 0)


add database dump local task

add database dump local task


move function definitions around. this is just cosmetic.

--- lib/assets/javascripts/edit_mode/best_in_place.js.coffee
+++ lib/assets/javascripts/edit_mode/best_in_place.js.coffee
@@ -1,16 +1,3 @@
-old_value = (best_in_place)->
-  if best_in_place.data('bip-original-content')?
-    best_in_place.data('bip-original-content')
-  else
-    null
-
-new_value = (best_in_place)->
-  v = best_in_place.find('input').val() if best_in_place.find('input').length > 0
-  v = best_in_place.find('textarea').text() if best_in_place.find('textarea').length > 0
-  v = best_in_place.find('select').find(":selected").text() if best_in_place.find('select').length > 0
-  v = null if v == ""
-  return v
-
 $(document).ready ->

   jQuery.fn.apply_best_in_place = ->
@@ -43,10 +30,22 @@

   $( ".best_in_place" ).apply_best_in_place()

+  old_value = (best_in_place)->
+    if best_in_place.data('bip-original-content')?
+      best_in_place.data('bip-original-content')
+    else
+      null
+
+  new_value = (best_in_place)->
+    v = best_in_place.find('input').val() if best_in_place.find('input').length > 0
+    v = best_in_place.find('textarea').text() if best_in_place.find('textarea').length > 0
+    v = best_in_place.find('select').find(":selected").text() if best_in_place.find('select').length > 0
+    v = null if v == ""
+    return v
+
   keyUpHandler = (event) ->
     if event.keyCode == 27
       $( this ).closest( ".edit_mode_group" ).trigger( "cancel" )
     if event.keyCode == 13
       unless $( event.target ).is( "textarea" )
         $( this ).closest( ".edit_mode_group" ).trigger( "save" )
-


Fix hawk middleware to only add payload hash when there is a request body

--- lib/assets/javascripts/marbles/middleware/hawk.js.coffee
+++ lib/assets/javascripts/marbles/middleware/hawk.js.coffee
@@ -16,10 +16,14 @@
     @options = options

   processRequest: (http) ->
-    header = hawk.client.header(http.method, http.url, _.extend({
-        credentials: @credentials
-        payload: http.body
-      }, @options)
+    options = {
+      credentials: @credentials
+    }
+    if http.body
+      options.payload = http.body
+      options.contentType = http.request.request_headers['Content-Type']
+
+    header = hawk.client.header(http.url, http.method, _.extend(options, @options)
     ).field
     return unless header


Track campfire room locked state

Track campfire room locked state

--- src/adapters/campfire.coffee
+++ src/adapters/campfire.coffee
@@ -50,7 +50,9 @@
     bot.on "TextMessage",
       withAuthor (id, created, room, user, body, author) ->
         unless bot.info.id is author.id
-          self.receive new TextMessage author, body, id
+          message = new TextMessage author, body, id
+          message.private = bot.private[room]
+          self.receive message

     bot.on "EnterMessage",
       withAuthor (id, created, room, user, body, author) ->
@@ -66,6 +68,14 @@
       withAuthor (id, created, room, user, body, author) ->
         unless bot.info.id is author.id
           self.receive new TopicMessage author, body, id
+
+    bot.on "LockMessage",
+      withAuthor (id, created, room, user, body, author) ->
+        bot.private[room] = true
+
+    bot.on "UnlockMessage",
+      withAuthor (id, created, room, user, body, author) ->
+        bot.private[room] = false

     bot.Me (err, data) ->
       bot.info = data.user
@@ -99,6 +109,7 @@
     @account       = options.account
     @host          = @account + ".campfirenow.com"
     @authorization = "Basic " + new Buffer("#{@token}:x").toString("base64")
+    @private       = {}

   Rooms: (callback) ->
     @get "/rooms", callback


set access to members only

set access to members only

--- src/adaptor/wordpress.coffee
+++ src/adaptor/wordpress.coffee
@@ -22,7 +22,7 @@

   buildThreadMapping: (pageNum) ->
     new Promise (resolve, reject) =>
-      filter = number: MAX_EXPECTED_WP_POSTS
+      filter = number: @MAX_EXPECTED_WP_POSTS
       @wordpress.getPosts filter, null, (error, posts) =>
         if error
           throw error
@@ -70,7 +70,10 @@
         raise error if error
         debug "Updated: #{post.info()}"
     else
-      data.custom_fields = [ {key: 'threadId', value: post.threadId} ]
+      data.custom_fields = [
+        {key: 'threadId', value: post.threadId}
+        {key: '_wpac_is_members_only', value: 'true'}
+      ]
       @wordpress.newPost data, (error, postId) ->
         raise error if error
         post.id = postId


[Activity] minor

[Activity] minor

--- client/app/Applications/Activity.kdapplication/ListItems/ActivityListItem.coffee
+++ client/app/Applications/Activity.kdapplication/ListItems/ActivityListItem.coffee
@@ -72,9 +72,9 @@
       @addChildView teaser, => @slideIn()

   slideIn:(callback=noop)->
-    @once 'transitionend', callback.bind @
+    @once 'transitionend', callback.bind this
     @unsetClass 'hidden-item'

   slideOut:(callback=noop)->
-    @once 'transitionend', callback.bind @
+    @once 'transitionend', callback.bind this
     @setClass 'hidden-item'


jQueryCompat

jQueryCompat

- fixed "hasClass" for Arrays
- fixed "find" for noop-node
- "length": output error message only if error level is big enough

--- src/base/jQueryCompat.coffee
+++ src/base/jQueryCompat.coffee
@@ -77,6 +77,20 @@
 							return nodes

 						return
+
+					if key in [
+						"hasClass"
+					]
+						nodes[key] = =>
+							for node in nodes
+								has_class =	node[key].apply(node, arguments)
+								if has_class
+									return true
+
+							return false
+
+						return
+

 					if key in [
 						"find"
@@ -179,6 +193,11 @@
 		node.length = 0

 		for key in @__noopKeys
+			if key == "find"
+				node[key] = =>
+					@__warn(key, "Noop node.")
+					return []
+
 			node[key] = =>
 				@__warn(key, "Noop node.")
 				return
@@ -207,7 +226,8 @@
 			enumerable: false
 			get: =>
 				CUI.jQueryCompat.__warn(".length", node)
-				console.error("jQueryCompat: .length accessed on node. Returning 1.", node)
+				if CUI.defaults.jQueryCompat > 1
+					console.error("jQueryCompat: .length accessed on node. Returning 1.", node)
 				return 1

 			set: =>


temp titles for verb selectors

temp titles for verb selectors

--- app/assets/javascripts/zvg/verbatim.coffee
+++ app/assets/javascripts/zvg/verbatim.coffee
@@ -36,12 +36,21 @@
     @renderCallback(@)

   initializeQuestionTable: ->
-    @controls        = d3.select(@container).append('div').attr('class', 'controls')
+    @controls        = d3.select(@container).append('table').attr('class', 'controls')
+    @control_row     = @controls.append('tr')
     @pagination      = d3.select(@container).append('div').attr('class', 'pagination')
     @question_table  = d3.select(@container).append('table').attr('class', 'verbatim')
-    @series_selector = @controls.append('select').attr('name', 'series_selector')
-    @filter_selector = @controls.append('select').attr('name', 'filter_selector')
-    @tag_selector = @controls.append('select').attr('name', 'tag_selector')
+
+    @series_cell     = @control_row.append('td')
+    @series_title    = @series_cell.append('h4').text('series_title').attr('class', 'verb_selector_title')
+    @series_selector = @series_cell.append('select').attr('name', 'series_selector')
+    @filter_cell     = @control_row.append('td')
+    @filter_title    = @filter_cell.append('h4').text('filter_title').attr('class', 'verb_selector_title')
+    @filter_selector = @filter_cell.append('select').attr('name', 'filter_selector')
+    @tag_cell        = @control_row.append('td')
+    @tag_title       = @tag_cell.append('h4').text('tag_title').attr('class', 'verb_selector_title')
+    @tag_selector    = @tag_cell.append('select').attr('name', 'tag_selector')
+

   constructDataFilter: (options) ->


Fixed BMS doc links

Fixed BMS doc links

--- app/controllers/building_simulation.coffee
+++ app/controllers/building_simulation.coffee
@@ -3,8 +3,8 @@
 module.exports = require("./simple_controller")
   caption: "Run Building Model Simulation"
   apis: [
-    {name: "Building Model: Create Building Model Action", path: "create_building_model_action"}
-    {name: "Building Model: Query Building Model Action", path: "query_building_model_action"}
+    {name: "Building Model: Create Building Model Simulation", path: "create_building_model_simulation"}
+    {name: "Building Model: Query Building Model Simulation", path: "query_building_model_simulation"}
   ]

   action: (env, events) ->


move ls -la from readstream

move ls -la from readstream

--- src/controllers/index.coffee
+++ src/controllers/index.coffee
@@ -47,12 +47,11 @@
     form_data = new FormData()
     #form_data.append 'photo', body

-    console.log 'read_stream is opened!!! executing ls -ls'
     exec "ls -la", (error, stdout, stderr) ->
       sys.puts stdout
-      console.log 'Error: ' + error
-      console.log 'Stdout: ' + stdout
-      console.log 'Stderr: ' + stderr
+      #console.log 'Error: ' + error
+      #console.log 'Stdout: ' + stdout
+      #console.log 'Stderr: ' + stderr

     read_stream = fs.createReadStream(__dirname + '/life_is_random.jpg')
     read_stream.on 'open', ->


Fixed OPT_REMOTE issue

Fixed OPT_REMOTE issue

--- app/assets/javascripts/ajax.js.coffee
+++ app/assets/javascripts/ajax.js.coffee
@@ -1,13 +1,10 @@
 #/* AJAX Functionality */

 @module "optemo_module", ->
-  #This variable is used to determine wether the code is embedded or not
-  if (typeof OPT_REMOTE is "undefined")
-    OPT_REMOTE = false
+
   #Set up the AJAX send function for use with the back button
-  $(document).ready( ->
+  $(document).ready ->
     $.history.init(optemo_module.ajaxsend,{unescape: true})
-  )

   #****Public Functions****
   # Submit a categorical filter, e.g. brand.
@@ -91,9 +88,9 @@
     if (/localhost/.test(myurl) or /192\.168/.test(myurl))
       val_timeout = 100000
     lis.socket_error_timer = setTimeout("optemo_module.ajaxerror()", val_timeout)
-    if (OPT_REMOTE)
+    if (window.OPT_REMOTE)
       #Embedded Layout
-      myurl = if(typeof myurl isnt "undefined" and myurl isnt null) then myurl.replace(/http:\/\/[^\/]+/,'') else "/compare"
+      myurl = if myurl? then myurl.replace(/http:\/\/[^\/]+/,'') else "/compare"
       # There is a bug in the JSONP implementation. If there is a "?" in the URL, with parameters already on it,
       # this JSONP implementation will add another "?" for the second set of parameters (specified in mydata).
       # For now, just check for a "?" and take those parameters into mydata,
@@ -108,7 +105,7 @@
           if(not mydata.hasOwnProperty(i)) # Do not merge properties that already exist.
             mydata[i] = content
         myurl = myurl.slice(0, myurl.indexOf('?'))
-      JSONP.get(OPT_REMOTE+myurl,mydata,ajaxhandler)
+      JSONP.get(window.OPT_REMOTE+myurl,mydata,ajaxhandler)
     else
       $.ajax(
         #type: (mydata==null)?"GET":"POST",
@@ -163,9 +160,9 @@

   #****Private Functions****
   quickajaxcall = (element_name, myurl, fn) -> # The purpose of this is to do an ajax load without having to go through the relatively heavy ajaxcall().
-    if (OPT_REMOTE)
+    if (window.OPT_REMOTE)
       #Check for absolute urls
-      JSONP.get(OPT_REMOTE+myurl.replace(/http:\/\/[^\/]+/,''), {embedding:'true', category_id: window.opt_category_id}, (data) ->
+      JSONP.get(window.OPT_REMOTE+myurl.replace(/http:\/\/[^\/]+/,''), {embedding:'true', category_id: window.opt_category_id}, (data) ->
         $(element_name).html(data)
         if (fn)
           fn()


Removed unwanted id parameter from ajax request for activating/deactivation cohorts

--- app/assets/javascripts/cohorts.coffee
+++ app/assets/javascripts/cohorts.coffee
@@ -9,7 +9,7 @@
       type: "PUT",
       url: "/cohorts/#{cohort_id}",
       dataType: "json"
-      data: { cohort: { id: cohort_id, active: !cohort_status} },
+      data: { cohort: { active: !cohort_status } },
       success:(data) ->
       	$('#cohort_status').val data.active
       	if data.active


fixed tap bug in mobile

fixed tap bug in mobile

--- app/assets/javascripts/general.coffee
+++ app/assets/javascripts/general.coffee
@@ -31,7 +31,7 @@
       "#link-about"
       "#logout-link"
       ".home-link"
-      # "#top-nav.open .task-link"
+      "#top-nav.open .task-link"
       ".score-save-link"
       ".sign-in-link"
       ".score-link"


Immediately disable Next Unread button when marking all read

--- app/assets/javascripts/main.js.coffee
+++ app/assets/javascripts/main.js.coffee
@@ -81,6 +81,7 @@

   if location.hash.match '#!/home'
     $('#group_view').empty().append(chunks.spinner.clone())
+    $('#next_unread').attr('href', '#')
     success = -> window.onhashchange()
   else
     $('#posts_list tbody tr').removeClass('unread')


Fix typo

Fix typo

My editor complains about semicolons in coffee, so it annoys me.

--- app/assets/javascripts/main.js.coffee
+++ app/assets/javascripts/main.js.coffee
@@ -4,4 +4,4 @@
 $.facebox.settings.loadingImage = '/assets/loading.gif'

 $ ->
-  window.FAYE_CLIENT = new Faye.Client('/faye');
+  window.FAYE_CLIENT = new Faye.Client('/faye')


Load data from the project object instead from the api

--- app/coffee/modules/common/tags.coffee
+++ app/coffee/modules/common/tags.coffee
@@ -196,17 +196,16 @@
                 menu.css("top", position.top)
                 menu.css("left", position.left)

-            $rs.projects.tags(project.id).then (data) ->
-                $el.find("input").autocomplete({
-                    source: data
-                    position: {
-                        my: "left top",
-                        using: positioningFunction
-                    }
-                    select: (event, ui) ->
-                        addValue(ui.item.value)
-                        ui.item.value = ""
-                })
+            $el.find("input").autocomplete({
+                source: _.keys(project.tags_colors)
+                position: {
+                    my: "left top",
+                    using: positioningFunction
+                }
+                select: (event, ui) ->
+                    addValue(ui.item.value)
+                    ui.item.value = ""
+            })

         $scope.$watch $attrs.ngModel, (tags) ->
             tagsColors = $scope.project?.tags_colors or []
@@ -384,17 +383,16 @@
                 menu.css("top", position.top)
                 menu.css("left", position.left)

-            $rs.projects.tags(project.id).then (data) ->
-                $el.find("input").autocomplete({
-                    source: data
-                    position: {
-                        my: "left top",
-                        using: positioningFunction
-                    }
-                    select: (event, ui) ->
-                        addValue(ui.item.value)
-                        ui.item.value = ""
-                })
+            $el.find("input").autocomplete({
+                source: _.keys(project.tags_colors)
+                position: {
+                    my: "left top",
+                    using: positioningFunction
+                }
+                select: (event, ui) ->
+                    addValue(ui.item.value)
+                    ui.item.value = ""
+            })

         $scope.$watch $attrs.ngModel, (model) ->
             return if not model


add observer for filter status

add observer for filter status

--- app/components/submission-list.coffee
+++ app/components/submission-list.coffee
@@ -13,8 +13,11 @@
     @get("store").findAll "submission"
   ).property "realtime.SubmissionCounter"

-  filteredSubmissions: Ember.computed.filter 'submissions', (submission) ->
-    submission.get("status") isnt ENUMS.SUBMISSION_STATUS.ANALYZING
+  submissionStatusObserver: Ember.observer "submissions.@each.status", ->
+    submissions = @get "submissions"
+    filteredSubmissions = submissions.filter (submission) ->
+      submission.get("status") isnt ENUMS.SUBMISSION_STATUS.ANALYZING
+    @set "filteredSubmissions", filteredSubmissions

   submissionSorting: ['id:desc']
   sortedSubmissions: Ember.computed.sort 'filteredSubmissions', 'submissionSorting'


update authorization error page detection

--- shared/js/src/content.coffee
+++ shared/js/src/content.coffee
@@ -155,7 +155,9 @@
       return

     @isAuthorisationErrorPage: (contents) ->
-      /reauth/i.test contents
+      (/reauth/i.test contents) or
+      (contents and contents.indexOf('continue%3Dhttps://api.mailfred.de/schedule') isnt -1) or
+      (contents and contents.indexOf('google.com/accounts/AddSession') isnt -1)

     @isAuthorisationErrorResponse: (resp) ->
       (resp?.toLowerCase().indexOf "authorization") isnt -1


removing unused 'fs' require in templateFinder

--- shared/templateFinder.coffee
+++ shared/templateFinder.coffee
@@ -1,4 +1,3 @@
-fs = require('fs') if global.isServer
 handlebarsHelpers = require('./handlebarsHelpers')

 templates = null


Remove unused function

Remove unused function

--- app/javascript/src/legacy/post.coffee
+++ app/javascript/src/legacy/post.coffee
@@ -11,21 +11,6 @@
     'circle'
     'faults'
   ]
-  find_similar: ->
-    old_source_name = $('post_source').name
-    old_file_name = $('post_file').name
-    old_target = $('edit-form').target
-    old_action = $('edit-form').action
-    $('post_source').name = 'url'
-    $('post_file').name = 'file'
-    $('edit-form').target = '_blank'
-    $('edit-form').action = 'http://danbooru.iqdb.hanyuu.net/'
-    $('edit-form').submit()
-    $('post_source').name = old_source_name
-    $('post_file').name = old_file_name
-    $('edit-form').target = old_target
-    $('edit-form').action = old_action
-    return
   make_request: (path, params, finished) ->
     new (Ajax.Request)(path,
       requestHeaders: 'X-CSRF-Token': jQuery('meta[name=csrf-token]').attr('content')


removed old js and added flip card

removed old js and added flip card

--- app/assets/javascripts/app.js.coffee
+++ app/assets/javascripts/app.js.coffee
@@ -15,15 +15,6 @@
     $this.parents(".panel-compra").find(".form-producto").slideDown()
     $this.removeClass "panel-collapsed"
     $this.removeClass("fa fa-chevron-down").addClass "fa fa-chevron-up"
-  return
-
-$(document).on 'ready page:load',
--> $(".tipo").each ->
-    tipo =  $(this).text()
-    switch tipo
-      when "MILITAR" then $(this).css("color","#94D5AD")
-      when "CIVIL" then $(this).css("color","#2dc1e6")
-      when "FAMILIAR" then $(this).css("color","#E77666")

 $ ->
   $("#input-search").on "keyup", ->
@@ -56,3 +47,6 @@
     $("#" + tog).prop "value", sel
     $("a[data-toggle=\"" + tog + "\"]").not("[data-title=\"" + sel + "\"]").removeClass("active").addClass "notActive"
     $("a[data-toggle=\"" + tog + "\"][data-title=\"" + sel + "\"]").removeClass("notActive").addClass "active"
+
+  $(".card").click ->
+    $(this).toggleClass "flipped"


increase zoom mapbox

increase zoom mapbox

--- app/assets/javascripts/map.js.coffee
+++ app/assets/javascripts/map.js.coffee
@@ -22,7 +22,7 @@
         mapbox.markers.interaction(markerLayer)
         map.addLayer(markerLayer);

-        map.zoom(10).center({ lat: lat, lon: lon })
+        map.zoom(15).center({ lat: lat, lon: lon })

         markerLayer.add_feature({
             geometry: {
@@ -35,6 +35,4 @@
         })
       )

-
-
 App.Utilities.Map = Map


remove duplication and extract resize function

--- app/assets/javascripts/papers.coffee
+++ app/assets/javascripts/papers.coffee
@@ -12,23 +12,22 @@
     $("#author-submit").addClass('disabled')
     $("#author-submit").prop('disabled', true)

-$(document).on 'change', '.pre-check', authorCheck
-
-$ ->
-  $("form#new_paper").submit ->
-    e.preventDefault()
-
-  clipboard = new Clipboard('.clippy')
-
+setPaperSize = ->
   if($("#joss-paper").length > 0)
     paper = $('#joss-paper')
     width = paper.width()
     height = width * 1.41421
     paper.css('height', height)

+$(document).on 'change', '.pre-check', authorCheck
+
 $(window).resize ->
-  if($("#joss-paper").length > 0)
-    paper = $('#joss-paper')
-    width = paper.width()
-    height = width * 1.41421
-    paper.css('height', height)
+  setPaperSize()
+
+$ ->
+  setPaperSize()
+
+  $("form#new_paper").submit ->
+    e.preventDefault()
+
+  clipboard = new Clipboard('.clippy')


added back in the offer detect..

added back in the offer detect..

--- app/assets/javascripts/webrtc.coffee
+++ app/assets/javascripts/webrtc.coffee
@@ -302,8 +302,7 @@
     peer_id = config.peer_id
     peer = @peers[peer_id]
     if( !peer )
-      alert('could not locate peer for peer id: '+peer_id)
-      ###
+      #alert('could not locate peer for peer id: '+peer_id)
       console.log('[WARN] - could not locate peer for peer id: '+peer_id)
       console.log('this must be the offer...')
       @doGetUserMedia( =>
@@ -311,7 +310,6 @@
         # now we have the peer so lets try this again.
         @sessionDescription(config)
       )
-      ###
     else
       remote_description = config.session_description
       console.log(config.session_description)


FIx conversation view

FIx conversation view

--- assets/javascripts/routers/posts.js.coffee
+++ assets/javascripts/routers/posts.js.coffee
@@ -28,8 +28,8 @@
   root: => @index(arguments...)

   conversation: (entity, post_id) =>
-    if @isAppSubdomain()
-      return @redirectToGlobalFeed()
+    if TentStatus.isAppSubdomain()
+      return TentStatus.redirectToGlobalFeed()
     unless post_id
       [post_id, entity] = [entity, TentStatus.config.domain_entity]
     else


Remove uiEvent unused directive.

Remove uiEvent unused directive.

--- app/coffee/directives/generic.coffee
+++ app/coffee/directives/generic.coffee
@@ -1,15 +1,3 @@
-UiEventDirective = ($parse) -> (scope, elm, attrs) ->
-    events = scope.$eval(attrs.uiEvent)
-    angular.forEach events,  (uiEvent, eventName) ->
-        fn = $parse(uiEvent)
-
-        elm.bind eventName,  (evt) ->
-            params = Array.prototype.slice.call(arguments)
-            params = params.splice(1)
-            scope.$apply ->
-                fn(scope, {$event: evt, $params: params})
-
-
 GmFileDirective = ($parse) ->
     require: "?ngModel",
     restrict: "A",
@@ -39,6 +27,5 @@

 module = angular.module('greenmine.directives.generic', [])
-module.directive('uiEvent', ['$parse', UiEventDirective])
 module.directive('gmFile', ["$parse", GmFileDirective])
 module.directive('gmFiles', ["$parse", GmFilesDirective])


sort buttons should have react key

sort buttons should have react key

--- resources/assets/coffee/react/beatmap-discussions/discussions.coffee
+++ resources/assets/coffee/react/beatmap-discussions/discussions.coffee
@@ -135,6 +135,7 @@
         span className: 'sort__item sort__item--title', osu.trans('sort._')
         for preset in presets
           button
+            key: preset
             type: 'button'
             className: "sort__item sort__item--button #{if @currentSort() == preset then 'sort__item--active' else ''}"
             'data-sort-preset': preset


Fix bug in handling of project root directory in erlc

--- lib/linter/erlc.coffee
+++ lib/linter/erlc.coffee
@@ -73,7 +73,7 @@
     directoryPath = path.dirname(@filePath)

     if directoryPath.endsWith('/src')
-      projectRoot = path.dirname(projectRoot)
+      projectRoot = path.dirname(directoryPath)
       command.push('-I', path.join(projectRoot, 'include'))
       command.push('-I', path.join(projectRoot, 'deps'))
       command.push('-pa', path.join(projectRoot, 'ebin'))


remove coffeescript file

remove coffeescript file

--- lib/misc/blocks.coffee
+++ lib/misc/blocks.coffee
@@ -1,91 +0,0 @@
-# TODO: docstrings
-
-scopes = require './scopes'
-
-module.exports =
-
-  getLine: (ed, l) ->
-    ed.getTextInBufferRange [[l, 0], [l, Infinity]]
-
-  isBlank: (l) -> l.match /^\s*(#.*)?$/
-  isEnd: (l) -> l.match /^end\b/
-  isCont: (l) -> l.match /^(else|elseif|catch|finally)\b/
-  isStart: (l) -> not (l.match(/^\s/) or @isBlank(l) or @isEnd(l) or @isCont(l))
-
-  walkBack: (ed, row) ->
-    while row > 0 and not @isStart @getLine ed, row
-      row--
-    row
-
-  walkForward: (ed, start) ->
-    mark = end = start
-    multiline = false
-    while mark < ed.getLastBufferRow()
-      mark++
-      l = @getLine ed, mark
-      if multiline
-        if l.match(/=#/) then multiline = false else continue
-      break if @isStart l
-      if @isEnd l
-        if not (scopes.forLines(ed, start, mark-1).length is 0)
-          end = mark
-      else if not (@isBlank(l) or @isStart(l))
-        end = mark
-      else if l.match(/#=/) and not l.match(/=#/)
-        multiline = true
-    end
-
-  getRange: (ed, row) ->
-    start = @walkBack ed, row
-    end = @walkForward ed, start
-    if start <= row <= end
-      [[start, 0], [end, Infinity]]
-
-  getSelection: (ed, sel) ->
-    {start, end} = sel.getBufferRange()
-    range = [[start.row, start.column], [end.row, end.column]]
-    while @isBlank(@getLine(ed, range[0][0])) and range[0][0] <= range[1][0]
-      range[0][0]++
-      range[0][1] = 0
-    while @isBlank(@getLine(ed, range[1][0])) and range[1][0] >= range[0][0]
-      range[1][0]--
-      range[1][1] = Infinity
-    range
-
-  moveNext: (ed, sel, [_, [row]]) ->
-    # Ensure enough room at the end of the buffer
-    while (last = ed.getLastBufferRow()) < row+2
-      break unless last is row or @isBlank @getLine ed, last
-      sel.setBufferRange [[last, Infinity], [last, Infinity]]
-      sel.insertText '\n'
-    # Move the cursor
-    to = row + 1
-    while to < ed.getLastBufferRow() and @isBlank @getLine ed, to
-      to++
-    to = @walkForward ed, to
-    sel.setBufferRange [[to, Infinity], [to, Infinity]]
-
-  getRanges: (ed) ->
-    ranges = for sel in ed.getSelections()
-      selection: sel
-      range:
-        if sel.isEmpty()
-          @getRange ed, sel.getHeadBufferPosition().row
-        else
-          @getSelection ed, sel
-    ranges.filter(({range})->range? and ed.getTextInBufferRange(range).trim())
-
-  get: (ed) ->
-    for {range, selection} in @getRanges ed
-      range: range
-      selection: selection
-      line: range[0][0]
-      text: ed.getTextInBufferRange range
-
-  select: (ed = atom.workspace.getActiveTextEditor()) ->
-    return unless ed?
-    ed.mutateSelectedText (selection) =>
-      {row} = selection.getHeadBufferPosition()
-      if (range = @getRange ed, row)
-        [start, [row]] = range
-        selection.setBufferRange [start, [row+1, 0]]


Show and hide auction bid data

Show and hide auction bid data

--- assets/coffee/auction-updates.coffee
+++ assets/coffee/auction-updates.coffee
@@ -1,5 +1,5 @@
 do ($=jQuery) ->
-    # FADE_SPEED = 75
+    FADE_SPEED = 200
     bidEntries = {}

     BID_EL_HEIGHT = 66
@@ -154,6 +154,16 @@
             $('*[data-no-bids]').hide()
         else
             $('*[data-no-bids]').show()
+
+        # show/hide ended explanation
+        if state.timePhase == 'ended'
+            if $('*[data-explanation-type=live]').is(':visible')
+                $('*[data-explanation-type=live]').fadeOut FADE_SPEED, ()->
+                    $('*[data-explanation-type=ended]').fadeIn FADE_SPEED
+        else
+            if $('*[data-explanation-type=ended]').is(':visible')
+                $('*[data-explanation-type=ended]').fadeOut FADE_SPEED, ()->
+                    $('*[data-explanation-type=live]').fadeIn FADE_SPEED

     initBidsByAddress = ()->


feat: add cache support

feat: add cache support


Bump new version

Bump new version

--- index.cjsx
+++ index.cjsx
@@ -42,7 +42,7 @@
   link: 'https://github.com/dazzyd'
   show: true
   priority: 8
-  version: '0.1.2'
+  version: '0.2.0'
   reactClass: React.createClass
     getInitialState: ->
       notifySecretary: config.get('plugin.secretary.ship', 0)


self != this. Ruby habits.

self != this. Ruby habits.

--- lib/script-view.coffee
+++ lib/script-view.coffee
@@ -47,7 +47,7 @@
     # Display window and load message

     # First run, create view
-    atom.workspaceView.prependToBottom self unless @hasParent()
+    atom.workspaceView.prependToBottom this unless @hasParent()

     # Close any existing process and start a new one
     @stop()


gravatarHash generator updated.

gravatarHash generator updated.

Now it uses displayName as source if there’s no emails defined. Still
needs a matching migration.

--- server/person.coffee
+++ server/person.coffee
@@ -15,8 +15,13 @@
         [fields._id, new Person(fields).getDisplayName()]

       fields.gravatarHash.generator = (fields) ->
-        address = fields.emails?[0]?.address
-        return [null, undefined] unless fields.person?._id and address
+        # Hash should come from user's email
+        source = fields.emails?[0]?.address
+
+        # Alternatively, if no email, use the display name
+        source = fields.person?.displayName unless source
+
+        return [null, undefined] unless fields.person?._id and source
         [fields.person._id, crypto.createHash('md5').update(address).digest('hex')]

       fields


fix: only restrict api routes

fix: only restrict api routes

--- server/server.coffee
+++ server/server.coffee
@@ -14,7 +14,7 @@
     secret: process.env.STRETCH_SESSION_SECRET
   ))

-app.all '*', (req, res, next) ->
+app.all '/api/*', (req, res, next) ->
   username = req.get('Sprintly-User')
   apiKey = req.get('Sprintly-Api-Key')
   req.session.credentials =


Remove compressible import

Remove compressible import

--- server/server.coffee
+++ server/server.coffee
@@ -7,7 +7,6 @@

 mongoose = require 'mongoose'
 express = require 'express'
-compressible = require 'compressible'
 path = require 'path'
 useragent = require 'express-useragent'
 http = require 'http'


Switching shipping to abstract

Switching shipping to abstract

--- src/features/shipping.coffee
+++ src/features/shipping.coffee
@@ -1,11 +1,3 @@
-	class Shipping
+	class Shipping extends Abstract

-		constructor: (@m) ->
-
-		Get: (id, callback, error) ->
-
-			return @m.Request 'shipping/'+id, 'GET', null, callback, error
-
-		List: (terms, callback, error) ->
-
-			return @m.Request 'shipping', 'GET', terms, callback, error
+		endpoint: 'shipping'


:lipstick:

:lipstick:

--- lib/spell-check.coffee
+++ lib/spell-check.coffee
@@ -1,3 +1,5 @@
+SpellCheckView = null
+
 module.exports =
   configDefaults:
     grammars: [
@@ -7,8 +9,8 @@
     ]

   createView: (editor) ->
-    @spellCheckViewClass ?= require './spell-check-view'
-    new @spellCheckViewClass(editor)
+    SpellCheckView ?= require './spell-check-view'
+    new SpellCheckView(editor)

   activate: ->
     rootView.eachEditor (editor) =>


Add feed link to menu

Add feed link to menu

--- web/src/views/main-menu.cjsx
+++ web/src/views/main-menu.cjsx
@@ -2,6 +2,8 @@
 require 'semantic-ui-css/components/menu.css'
 require 'semantic-ui-css/components/sidebar.css'
 require '../../css/menu.css'
+
+api = require '../backend.coffee'

 React = require 'react'

@@ -27,4 +29,8 @@

                 Geocache Map

+
+
+                Atom feed
+


(FIND-1500, CCUK-2403) Confirmed the approach works on Windows (potentially expected trouble since the source map in and out files have the same name, presumably it uses a buffer internally so doesn't have problems). Minify the languages files as well, since they're fetched separately outside the require.js preload.

--- webapp/idol/Gruntfile.coffee
+++ webapp/idol/Gruntfile.coffee
@@ -165,12 +165,20 @@
         mangle: true
         sourceMap: true
         sourceMapName: (file) -> file + '.map'
-        sourceMapIn: (file) -> file + '.map'
       js:
+        options:
+          sourceMapIn: (file) -> file + '.map'
         files: [{
           expand: true
           cwd: 'target/classes/static/js'
           src: ['public.js', 'config.js', 'login.js']
+          dest: 'target/classes/static/js'
+        }]
+      languages:
+        files: [{
+          expand: true
+          cwd: 'target/classes/static/js'
+          src: ['find/**/nls/**/*.js']
           dest: 'target/classes/static/js'
         }]

@@ -190,5 +198,5 @@
   grunt.registerTask 'watch-test', ['babel:transform', 'jasmine:test', 'watch:test']
   grunt.registerTask 'copy-resources', ['sync:devResources', 'watch:copyResources']
   grunt.registerTask 'concatenate', ['requirejs']
-  grunt.registerTask 'minify', ['uglify:js']
+  grunt.registerTask 'minify', ['uglify:js', 'uglify:languages']
   grunt.registerTask 'compile', ['concatenate', 'minify']