Fix staging signup

Fix staging signup

--- app/assets/javascripts/admin/views/connections/new.js.coffee
+++ app/assets/javascripts/admin/views/connections/new.js.coffee
@@ -59,7 +59,7 @@
     if env == 'custom'
       Augury.url = @$el.find('input.url').val()
     else
-      Augury.url = Augury.SignUp[env]
+      Augury.url = Augury.SignUp.urls[env]

   login: ->
     @set_url()


Fixed form names, params.headerText/params.HeaderText and params.message/params.Message.

--- app/assets/javascripts/app/controllers/maintenance.js.coffee
+++ app/assets/javascripts/app/controllers/maintenance.js.coffee
@@ -1,13 +1,13 @@
 class App.Maintenance extends App.ControllerContent
   events:
     'submit form': 'sendMessage'
+
   constructor: ->
     super
     # render page
     @render()

   render: ->
-
     @html App.view('maintenance')()

   sendMessage: (e) ->
@@ -18,9 +18,11 @@
           action: 'broadcast'
           event:  'session:maintenance'
           spool:  false
-          data:   {title: params.headerText, message: params.message}
+          data:
+            title:   params.HeaderText
+            message: params.Message
       )

 App.Config.set( 'maintenance', App.Maintenance, 'Routes' )
-App.Config.set( 'maintenance', { prio: 3600, parent: '#admin', name: 'Maintenance Message', target: '#maintenance', role: ['Admin'] }, 'NavBar' )+App.Config.set( 'maintenance', { prio: 3600, parent: '#admin', name: 'Maintenance Message', target: '#maintenance', role: ['Admin'] }, 'NavBar' )


Change order and style

Change order and style

--- public/coffeescripts/portfolio.coffee
+++ public/coffeescripts/portfolio.coffee
@@ -20,7 +20,13 @@
     ').append $('.itemInfoOverlay .loading').clone().removeClass 'main'
     $('.itemInfoOverlay .temp').remove()
     $('.itemInfoOverlay .info .title, .itemInfoOverlay .info .value').show()
-    $('.itemInfoOverlay .loading.main').fadeOut()
+    if data.itemType == 'item' && data.parentCollection
+      $('.itemInfoOverlay .buttonContainer .parent').removeClass('disabled').attr 'target', data.parentCollection
+      getData('collection', data.parentCollection).then (res) ->
+        $('.itemInfoOverlay .col-lg-9 .main').prepend $('
Part of Collection - ' + res.name + '
')
+        $('.itemInfoOverlay .loading.main').fadeOut()
+    else
+      $('.itemInfoOverlay .loading.main').fadeOut()
     projInfo = (callback) ->
       $('.itemInfoOverlay .main .title').text data.name
       $('.itemInfoOverlay .main .date').text data.date
@@ -30,14 +36,8 @@
       $('.info .proj .type').text data.type
       $('.info .proj .status').text data.status
       $('.info .proj .client').text data.for
-      if data.link
-        $('.info .proj .link').text data.link
-      else
-        $('.info .proj .link').text 'Unavaliable'
-      if $.isArray data.technologies
-        $('.info .proj .technologies').text data.technologies.join(', ')
-      else
-        $('.info .proj .technologies').text data.technologies
+      if data.link then $('.info .proj .link').text data.link else $('.info .proj .link').text 'Unavaliable'
+      if $.isArray data.technologies then $('.info .proj .technologies').text data.technologies.join(', ') else $('.info .proj .technologies').text data.technologies
       callback()
     teamInfo = (callback) ->
       if data.parentTeam
@@ -45,19 +45,20 @@
           team = res
           $('.info .team .name').text team.name
           $('.info .team .status').text team.status
-          if team.link
-            $('.info .team .link').text team.link
-          else
-            $('.info .team .link').text 'Unavaliable'
+          if team.link then $('.info .team .link').text team.link else $('.info .team .link').text 'Unavaliable'
           callback()
       else
         $('.info .team').append $('
Unavaliable
')
         $('.info .team .title, .info .team .value').hide()
         callback()
     childInfo = (callback) ->
-      getChildren('item', data._id).then (res) ->
-        for child in res
-          $('.info .child').append $('
' + child.name + '
')
+      if data.itemType == 'collection'
+        getChildren('item', data._id).then (res) ->
+          for child in res
+            $('.info .child').append $('
' + child.name + '
')
+          callback()
+      else
+        $('.info .child').append $('
Unavaliable
')
         callback()
     projInfo ->
       $('.itemInfoOverlay .info .proj .loading').fadeOut 500, ->
@@ -69,10 +70,7 @@
       $('.itemInfoOverlay .info .child .loading').fadeOut 500, ->
         $(this).remove()
     if data.showcase == 'true'
-      $('.itemInfoOverlay .showcase').removeClass 'disabled'
-      $('.itemInfoOverlay .showcase').attr 'href', 'showcases/' + data.itemType + '/' + data._id
-    if data.parentCollection
-      return
+      $('.itemInfoOverlay .buttonContainer .showcase').removeClass('disabled').attr 'href', 'showcases/' + data.itemType + '/' + data._id

   setGrid = (selec, callback) ->
     $(".allWorkContainer .row").rowGrid {


activity: simplify `ActivityListController` instantiation in `MessagePane` class

--- client/Social/Activity/messagepane.coffee
+++ client/Social/Activity/messagepane.coffee
@@ -9,10 +9,9 @@

     channel           = @getData()
     {itemClass, type} = @getOptions()
+    lastToFirst = yes  if type is "message"

-    @listController = new ActivityListController
-      itemClass     : itemClass
-      lastToFirst   : yes  if type is 'message'
+    @listController = new ActivityListController {itemClass, lastToFirst}
     @createInputWidget()


Removed comments blocking content formatting, made an issue addressing it instead.

--- client/coffeescript/templates/post.coffee
+++ client/coffeescript/templates/post.coffee
@@ -5,7 +5,7 @@
     2. Raw input converted using Showdown.
     3. Output of step 2 is subjected to Whitelist.
     4. Links are made ready for oembed.
-
+    ###
     #1. @content contains the raw input.
     raw_input = @content
     #2. Convert raw input using Showdown.
@@ -21,8 +21,7 @@
     oembedded = oembedded.replace(/(\s|>|^)(mailto:[^\s<]*)/igm, replacement)
     Meteor.defer( -> $('a.oembed').oembed().removeClass('oembed') )
     return oembedded
-    ###
-    return @content
+
   identifier: -> @_id
   link_href: ->
     return "/#{ @_id }"


Store invalid decimal values in state, apply later

This is needed so you can type '0.' before finishing with 0.2 for instance

--- client/lanes/components/shared/Input.cjsx
+++ client/lanes/components/shared/Input.cjsx
@@ -1,15 +1,17 @@
 class Lanes.Components.Input extends Lanes.React.Component
+
+    NUMBER_TEST: /^-?\d+(\.\d+)?$/

     mixins: [
         Lanes.Components.Form.FieldMixin
     ]
-    formGroupClass: 'input'
+
+    propTypes:
+        unlabled:  React.PropTypes.bool
+        onlyNumeric: React.PropTypes.bool

     getDefaultProps: ->
         type: 'text'
-
-    propTypes:
-        unlabled:  React.PropTypes.bool

     getValue: ->
         @refs.input.getValue()
@@ -17,8 +19,20 @@
     handleKeyDown: (ev) ->
         @props.onEnter() if ev.key is 'Enter'

+    valueInFlux: (value) ->
+        type = @props.model.attributeType(@props.name)
+        (@props.onlyNumeric or type is "bigdec" ) and not @NUMBER_TEST.test(value)
+
+    validatedChangeHandler: (ev) ->
+        value = ev.target.value
+        if @valueInFlux(value)
+            @setState(pendingValue: value)
+        else
+            @setState(pendingValue: false)
+            @handleChange(ev)
+
     renderEdit: (label) ->
-        value = @_getValue() or ''
+        value = @state.pendingValue or @props.value or @_getValue()
         label ||= @props.label or _.field2title(@props.name)
         props = _.extend({
             ref:       'input'
@@ -26,8 +40,8 @@
             label:     if @props.unlabeled then false else label
             value:     value
             onKeyDown: @handleKeyDown if @props.onEnter
-            onChange:  @handleChange
-        }, @props)
+            onChange:  @validatedChangeHandler
+        }, @props, {value: value})
         if @props.inputOnly then @renderPlain(props) else @renderStyled(props, label)

     renderPlain: (props) ->


Set default values for add and remove, thus eliminating some conditional detections.

--- LinkedList.coffee
+++ LinkedList.coffee
@@ -6,61 +6,38 @@
 	this.head = undefined
 	this.length = 0

-LinkedList.prototype.add = (value, position) ->
+LinkedList.prototype.add = (value, position = this.length) ->
+	if position < 0 or position > this.length then return
 	nodeToAdd = new Node(value)
-	if position is undefined
-		if this.length is 0
-			this.head = nodeToAdd
-		else
-			currentNode = this.head
-			until currentNode.next is undefined
-				currentNode = currentNode.next
-			currentNode.next = nodeToAdd
+	if position is 0
+		# If empty, oldHead is undefined
+		oldHead = this.head
+		this.head = nodeToAdd
+		nodeToAdd.next = oldHead
 	else
-		if position < 0 or position > this.length then return
 		currentNode = this.head
-		# Get to the node before the inserting position.
-		# Explicit increment by 1, since [0...-1] is [0].
-		for i in [0...position - 1] by 1
+		# Get to the node before the insertion position.
+		for i in [0...position - 1]
 			currentNode = currentNode.next
-		if position is 0
-			oldHead = this.head
-			this.head = nodeToAdd
-			nodeToAdd.next = oldHead
-		else
-			oldCurrentNodeNext = currentNode.next
-			currentNode.next = nodeToAdd
-			nodeToAdd.next = oldCurrentNodeNext
+		oldCurrentNodeNext = currentNode.next
+		currentNode.next = nodeToAdd
+		nodeToAdd.next = oldCurrentNodeNext
 	this.length++
 	return nodeToAdd.value

-LinkedList.prototype.remove = (position) ->
-	if this.length is 0 then return
-	if position is undefined
-		if this.length is 1
-			nodeToRemove = this.head
-			this.head = undefined
-		else
-			currentNode = this.head
-			# Get to the node before the one to remove
-			until currentNode.next.next is undefined
-				currentNode = currentNode.next
-			nodeToRemove = currentNode.next
-			currentNode.next = nodeToRemove.next
+LinkedList.prototype.remove = (position = this.length - 1) ->
+	if this.length is 0 or position < 0 or position >= this.length then return
+	if this.length is 1 or position is 0
+		nodeToRemove = this.head
+		# In the case of length === 1, this.head.next is undefined
+		this.head = this.head.next
 	else
-		if position < 0 or position >= this.length then return
 		currentNode = this.head
-		if position is 0
-			nodeToRemove = this.head
-			this.head = nodeToRemove.next
-		else
-			# Get to the node before the removing position.
-			# Explicit increment by 1, since [0...-1] is [0].
-			for i in [0...position - 1] by 1
-				currentNode = currentNode.next
-			nodeToRemove = currentNode.next
-			currentNode.next = nodeToRemove.next
-
+		# Get to the node before the removing position.
+		for i in [0...position - 1]
+			currentNode = currentNode.next
+		nodeToRemove = currentNode.next
+		currentNode.next = nodeToRemove.next
 	this.length--
 	return nodeToRemove.value


Saco logs

Saco logs

--- src/observers/incidentsApi.observer.coffee
+++ src/observers/incidentsApi.observer.coffee
@@ -17,7 +17,6 @@
       $message
       .tap (message) => debug "To publish message %o", message
       .then (message) => @messageSender.send message
-      .tap () => console.log("DONE")

     _mapper: (id, notification, err) ->
       Promise.props


constrain the annotation call-out horizontally so it is always visible in the window

--- common/lib/xmodule/xmodule/js/src/annotatable/display.coffee
+++ common/lib/xmodule/xmodule/js/src/annotatable/display.coffee
@@ -73,8 +73,13 @@
             classes: 'ui-tooltip-annotatable'
         events:
             show: @onShowTip
-
-    onShowTip: (event, api) => event.preventDefault() if @annotationsHidden
+            visible: @onVisibleTip
+
+    onShowTip: (event, api) =>
+        event.preventDefault() if @annotationsHidden
+
+    onVisibleTip: (event, api) =>
+        @constrainTipHorizontally(api.elements.tooltip, event.originalEvent.pageX)

     onClickToggleAnnotations: (e) => @toggleAnnotations()

@@ -199,7 +204,19 @@
             $(el).qtip('show')
             api = $(el).qtip('api')
             $(api?.elements.tooltip).offset(offset)
-
+
+    constrainTipHorizontally: (tip, mouseX) ->
+        win_width = $(window).width()
+        tip_center = $(tip).width() / 2 # see position setting of tip
+        tip_offset = $(tip).offset()
+
+        if (tip_center + mouseX) > win_width
+          adjust_left = '-=' + (tip_center + mouseX - win_width)
+        else if (mouseX - tip_center) < 0
+          adjust_left = '+=' + (tip_center - mouseX)
+
+        $(tip).animate({ left: adjust_left }) if adjust_left?
+
     _once: (fn) ->
         done = false
         return =>


Render load views prior to data fetching

--- coffee/cilantro/ui/workflows/query.coffee
+++ coffee/cilantro/ui/workflows/query.coffee
@@ -1,9 +1,10 @@
 define [
-    '../../core'
+    '../core'
+    '../base'
     '../concept'
     '../context'
     'tpl!templates/workflows/query.html'
-], (c, concept, context, templates...) ->
+], (c, base, concept, context, templates...) ->

     templates = c._.object ['query'], templates

@@ -19,10 +20,15 @@
             context: '.context-panel'

         onRender: ->
-            @concepts.show new concept.ConceptPanel
-                collection: c.data.concepts.queryable
+            @workspace.show new concept.ConceptWorkspace

-            @workspace.show new concept.ConceptWorkspace
+            # Deferred loading of views..
+            @concepts.show new base.LoadView
+            @context.show new base.LoadView
+
+            c.data.concepts.ready =>
+                @concepts.show new concept.ConceptPanel
+                    collection: c.data.concepts.queryable

             c.data.contexts.ready =>
                 @context.show new context.Context


ValueSlider: min/max options

ValueSlider: min/max options

--- coffee/src/views/value_slider_view.coffee
+++ coffee/src/views/value_slider_view.coffee
@@ -22,6 +22,8 @@
     value: 100
     handle: true
     draggable: true
+    min: 0
+    max: 100

   template: _.template '''
@@ -39,8 +41,8 @@

     # initialize value bar
     options =
-      low: 0
-      high: @_value
+      low: @options.min
+      high: @options.max
       draggable: false # make all value adjustments in-house
       extraClasses: 'value-bar-view'
     @_valueBar = new acorn.player.SlidingBarView options


Added missing space in "goto".

Added missing space in "goto".

--- src/scripts/location-decision-maker.coffee
+++ src/scripts/location-decision-maker.coffee
@@ -72,4 +72,4 @@
     else
       location = msg.random grouplocations

-      msg.send "I think you should goto #{location}"+      msg.send "I think you should go to #{location}"


change some style between frames

change some style between frames

--- src/smc-webapp/code-editor/frame-tree.cjsx
+++ src/smc-webapp/code-editor/frame-tree.cjsx
@@ -37,11 +37,11 @@
 drag_offset = if feature.IS_TOUCH then 5 else 1

 cols_drag_bar =
-    border       : "#{drag_offset}px solid #{bar_color}"
+    #border       : "#{drag_offset}px solid #{bar_color}"
+    padding      : "#{drag_offset}px"
+    background   : "lightgrey"
     zIndex       : 10
-    padding      : 0.5
     cursor       : 'ew-resize'
-    borderRadius : '2px'

 rows_drag_bar = misc.merge(misc.copy(cols_drag_bar), {cursor:'ns-resize'})


Fixed: tooltip were not properly positionned when the window was scrolled.

--- src/aria-tips.coffee
+++ src/aria-tips.coffee
@@ -90,6 +90,10 @@
             x: 0 | boundingBox.left + (boundingBox.right - boundingBox.left) / 2
             y: 0 | boundingBox.top + (boundingBox.bottom - boundingBox.top) / 2

+        # Add page offset to get the right position when the page is scrolled.
+        center.x = center.x + window.pageXOffset
+        center.y = center.y + window.pageYOffset
+
         # Initialize the tooltip positionning.
         result =
             top:    'auto'
@@ -99,10 +103,14 @@

         # Get the direction's position value.
         position = switch direction
-            when 'top'    then window.innerHeight - boundingBox.top
-            when 'bottom' then boundingBox.bottom
-            when 'left'   then window.innerWidth - boundingBox.left
-            when 'right'  then boundingBox.right
+            when 'top'
+                window.innerHeight - boundingBox.top - window.pageYOffset
+            when 'bottom'
+                boundingBox.bottom + window.pageYOffset
+            when 'left'
+                window.innerWidth - boundingBox.left - window.pageXOffset
+            when 'right'
+                boundingBox.right + window.pageXOffset

         # Get the opposite direction's position value.
         oppositeDirection = oppositePosition direction


hides the admin checkboxes in annotator

hides the admin checkboxes in annotator

--- app/assets/javascripts/annotatable.js.coffee
+++ app/assets/javascripts/annotatable.js.coffee
@@ -6,11 +6,14 @@
       ann_id      = $this.data("annotatable-id")

       app = new annotator.App()
-        .include(annotator.ui.main, { element: this })
-        .include(annotator.storage.http, { prefix: "", urls: { search: "/annotations/search" } })
         .include ->
           beforeAnnotationCreated: (ann) ->
             ann[ann_type + "_id"] = ann_id
+            ann.permissions = ann.permissions || {}
+            ann.permissions.admin = []
+        .include(annotator.ui.main, { element: this })
+        .include(annotator.storage.http, { prefix: "", urls: { search: "/annotations/search" } })
+

       app.start().then ->
         app.ident.identity = $('html').data('current-user-id')


Lowercase 'e'

Lowercase 'e'

--- app/assets/javascripts/application.js.coffee
+++ app/assets/javascripts/application.js.coffee
@@ -35,7 +35,7 @@

   defaultBio: ->
     """
-    Hi Everyone, I'm Maeby! I love coding in VB6 across the stack.
+    Hi everyone, I'm Maeby! I love coding in VB6 across the stack.
      I also ping-pong a lot between concept and design. Hoping to get involved
      with UX, to help kickstart ideas, and to provide tangible feedback.


Fixed issue based on feedback

Fixed issue based on feedback

--- app/assets/javascripts/gl_dropdown.js.coffee
+++ app/assets/javascripts/gl_dropdown.js.coffee
@@ -1,5 +1,6 @@
 class GitLabDropdownFilter
   BLUR_KEYCODES = [27, 40]
+  ARROW_KEY_CODES = [38, 40]
   HAS_VALUE_CLASS = "has-value"

   constructor: (@input, @options) ->
@@ -22,19 +23,23 @@
     # Key events
     timeout = ""
     @input.on "keyup", (e) =>
+      keyCode = e.which
+
+      return if ARROW_KEY_CODES.indexOf(keyCode) >= 0
+
       if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS
         $inputContainer.addClass HAS_VALUE_CLASS
       else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS
         $inputContainer.removeClass HAS_VALUE_CLASS

-      if e.keyCode is 13 and @input.val() isnt ""
+      if keyCode is 13 and @input.val() isnt ""
         if @options.enterCallback
           @options.enterCallback()
         return

       clearTimeout timeout
       timeout = setTimeout =>
-        blur_field = @shouldBlur e.keyCode
+        blur_field = @shouldBlur keyCode
         search_text = @input.val()

         if blur_field and @filterInputBlur
@@ -96,7 +101,7 @@
   LOADING_CLASS = "is-loading"
   PAGE_TWO_CLASS = "is-page-two"
   ACTIVE_CLASS = "is-active"
-  CURRENT_INDEX = -1
+  currentIndex = -1

   FILTER_INPUT = '.dropdown-input .dropdown-input-field'

@@ -146,7 +151,7 @@
         data: =>
           return @fullData
         callback: (data) =>
-          CURRENT_INDEX = -1
+          currentIndex = -1
           @parseData data
         enterCallback: =>
           if @enterCallback
@@ -311,11 +316,11 @@
       if @highlight
         text = @highlightTextMatches(text, @filterInput.val())

-      html = "
"
-      html += ""
-      html += text
-      html += ""
-      html += "
"
+      html = "

+
+          #{text}
+
+
"

     return html

@@ -398,31 +403,31 @@
       selector = ".dropdown-page-one #{selector}"

     $('body').on 'keydown', (e) =>
-      currentKeyCode = e.keyCode
+      currentKeyCode = e.which

       if ARROW_KEY_CODES.indexOf(currentKeyCode) >= 0
         e.preventDefault()
-        e.stopPropagation()
-
-        PREV_INDEX = CURRENT_INDEX
+        e.stopImmediatePropagation()
+
+        PREV_INDEX = currentIndex
         $listItems = $(selector, @dropdown)

-        if @options.filterable
-          $input.blur()
+        # if @options.filterable
+        #   $input.blur()

         if currentKeyCode is 40
           # Move down
-          CURRENT_INDEX += 1 if CURRENT_INDEX < ($listItems.length - 1)
+          currentIndex += 1 if currentIndex < ($listItems.length - 1)
         else if currentKeyCode is 38
           # Move up
-          CURRENT_INDEX -= 1 if CURRENT_INDEX > 0
-
-        @highlightRowAtIndex($listItems, CURRENT_INDEX) if CURRENT_INDEX isnt PREV_INDEX
+          currentIndex -= 1 if currentIndex > 0
+
+        @highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX

         return false

       if currentKeyCode is 13
-        @selectRowAtIndex CURRENT_INDEX
+        @selectRowAtIndex currentIndex

   removeArrayKeyEvent: ->
     $('body').off 'keydown'
@@ -437,13 +442,13 @@

     # Dropdown content scroll area
     $dropdownContent = $listItem.closest('.dropdown-content')
-    dropdownScrollTop = $dropdownContent.prop('scrollTop')
-    dropdownContentHeight = $dropdownContent.prop('offsetHeight')
+    dropdownScrollTop = $dropdownContent.scrollTop()
+    dropdownContentHeight = $dropdownContent.outerHeight()
     dropdownContentTop = $dropdownContent.prop('offsetTop')
     dropdownContentBottom = dropdownContentTop + dropdownContentHeight

     # Get the offset bottom of the list item
-    listItemHeight = $listItem.prop('offsetHeight')
+    listItemHeight = $listItem.outerHeight()
     listItemTop = $listItem.prop('offsetTop')
     listItemBottom = listItemTop + listItemHeight


use JSCocoa to eval require.js - shows up in web inspector!

--- src/bootstrap.coffee
+++ src/bootstrap.coffee
@@ -8,8 +8,8 @@

 # load require() function
 root = OSX.NSBundle.mainBundle.resourcePath
-code = OSX.NSString.stringWithContentsOfFile "#{root}/src/require.js"
-eval "(function(){ #{code} })(this);"
+code = OSX.NSString.stringWithContentsOfFile path = "#{root}/src/require.js"
+__jsc__.evalJSString_withScriptPath code, path

 console.log 'require tests:'
 console.log require.resolve 'underscore'


Fix array points kept in reference

Fix array points kept in reference

--- app/scripts/lib/script_modules/entity.coffee
+++ app/scripts/lib/script_modules/entity.coffee
@@ -101,7 +101,7 @@
   # - speed: override the speed of the entity (in px/sec)
   # - rotate: yes/no should the entity rotate along the path?
   # - skip: amount of milliseconds to skip in this animation
-  movePath: (path, settings = {}) ->
+  movePath: (inputPath, settings = {}) ->
     (sequence) =>
       @_verify(sequence)
       return unless @enemy.alive
@@ -109,7 +109,10 @@
         rotate: yes
         skip: 0
         speed: @entity.speed
+        continuePath: no
       )
+      path = [].concat inputPath
+
       path.unshift [
         Math.round(@entity.x + Crafty.viewport.x)
         Math.round(@entity.y + Crafty.viewport.y)
@@ -139,7 +142,9 @@
         c = Math.sqrt(a**2 + b**2)
         d += c
         pp = pn
-        { x: x - Crafty.viewport.x, y: y - Crafty.viewport.y }
+        x -= Crafty.viewport.x
+        y -= Crafty.viewport.y
+        { x, y }
       )
       duration = (d / settings.speed) * 1000

@@ -148,6 +153,7 @@
         [
           type: 'viewportBezier'
           rotation: settings.rotate
+          continuePath: settings.continuePath
           path: bezierPath
           duration: duration
         ], skip: settings.skip


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/clampable.coffee
+++ src/clampable.coffee
@@ -2,7 +2,10 @@
 The Clampable module provides helper methods to clamp object properties.

     player = GameObject
-      x:
+      x: 40
+      y: 30
+
+

 @name Clampable
 @module


preserve tmp

preserve tmp

--- src/command/dir.iced
+++ src/command/dir.iced
@@ -27,15 +27,17 @@
     await write_tmp_file { data, base : file, mode : 0o600 }, defer err, nm
     unless err?
       @_tmp_files[file] = nm
+      log.debug "| tmpfile #{nm}"
     cb err

   #---------------

   cleanup_run1 : (cb) ->
-    for k,v of @_tmp_files
-      await fs.unlink v, defer err
-      if err?
-        log.warn "Could not remove tmp file #{v}: #{err.message}"
+    unless @argv.preserve_tmp_files
+      for k,v of @_tmp_files
+        await fs.unlink v, defer err
+        if err?
+          log.warn "Could not remove tmp file #{v}: #{err.message}"
     cb()

   #---------------
@@ -109,6 +111,10 @@
       alias:        'strict'
       action:       'storeTrue'
       help:         'fail on warnings (typically cross-platform problems)'
+    P :
+      alias:        'preserve-tmp-files'
+      action:       'storeTrue'
+      help:         'preserve temp files for debugging and inspection'
     # dir: this is added below, since the nargs format doesn't work
     #   with the add_option_dict function


removes the restore method from test

removes the restore method from test

--- components/artwork_filter/test/view.coffee
+++ components/artwork_filter/test/view.coffee
@@ -17,7 +17,6 @@
       done()

   after ->
-    @setStub.restore()
     benv.teardown()

   beforeEach ->


Do not return remotepass values to the client in any case

--- kites/sharedHosting/api.coffee
+++ kites/sharedHosting/api.coffee
@@ -25,7 +25,15 @@

   executeCommand: require './executecommand'

-  readMountInfo: (options, callback)-> mounter.readMountInfo options, callback
+  readMountInfo: (options, callback)->
+    mounter.readMountInfo options, (err, res)->
+      if err then callback err
+      else
+        for mount,i in res
+          delete mount.remotepass
+          res[i] = mount
+        callback err, res
+
   mountFtpDrive: (options, callback)-> mounter.mountFtpDrive options, callback
   mountDrive   : (options, callback)-> mounter.mountDrive    options, callback
   umountDrive  : (options, callback)-> mounter.umountDrive   options, callback


proof of concept

proof of concept

--- src/dt-jquery.coffee
+++ src/dt-jquery.coffee
@@ -14,9 +14,63 @@
 # TODO mit canvas tag kommt man direkt auf die browser render ticks.

+# multiple changes of this context possible
+singlton_callback = (that, callback) ->
+    req = -> callback?.apply(that, arguments)
+    req.replace = (replacement) -> that = req.that = replacement
+    req.that = that
+#     req.callback = callback?.callback
+#     req.cancel = callback?.cancel
+    return req
+
+cancelable_callback = (callback) ->
+    canceled = no
+    cb = -> callback?() unless canceled
+    cb.cancel = -> canceled = yes
+    cb.cancel.reset = -> canceled = no
+#     cb.callback = callback?.callback
+#     cb.replace = callback?.replace
+    return cb
+
+deferred_callbacks = () ->
+    done = no
+    callbacks = []
+    res = (cb) ->
+        return cb?() if done
+        callbacks.push(cb)
+    allowed = null
+    res.callback = ->
+        return (->) if done
+        callback = ->
+            if callback is allowed
+                while (cb = callbacks.shift())?
+                    cb?(arguments...)
+                callbacks = null
+                allowed = null
+                done = yes
+        allowed = callback
+        return callback
+    return res
+
+cancelable_and_retrivable_callbacks = () ->
+    canceled = no
+    res = (cb) ->
+        return ->
+            if canceled
+                res.callbacks.push(cb)
+            else
+                cb?(arguments...)
+    res.cancel = -> canceled = yes
+    res.reset = -> canceled = no
+    res.callbacks = []
+    return res
+
+
 removed = (el) ->
     el.closed is "removed"

+
+# NOTE delay and release are only for manipulations where no parent is needed
 # delay or invoke job immediately
 delay = (job) ->
     return if removed this
@@ -51,7 +105,10 @@

     initialize: () ->
         do @listen
-        @builder._jquery_tracker = el:@builder
+        # prefill builder with state
+        @builder._jquery = $([])
+        @builder._jquery_done = deferred_callbacks()
+        do @builder._jquery_done.callback() # builder is allways done
         # override query
         old_query = @builder.query
         @builder.query = (type, tag, key) ->
@@ -93,65 +150,120 @@
     # eventlisteners

     onadd: (parent, el) ->
-        el._jquery_tracker = {el}
-        # insert into parent
         that = this
-        delay.call parent, -> # !
-            el = el?._jquery_tracker?.el
-            return if not el or removed this
-            if this is @builder and @_jquery.parent().length is 0
-                @_jquery = @_jquery.add(el._jquery)
-#                 parent._jquery.data('dt-jquery', parent)
-#                 console.error "ready!", el.name, el._jquery_ready
-                el._jquery_ready?()
-                el._jquery_ready = yes
+        # `this` changes in onreplace
+        el._jquery_insert ?= singlton_callback el, ->
+            return if removed this
+            if @parent is @parent.builder
+                $root = @parent._jquery.parent()
+                if $root.length is 0
+                    jq = @parent._jquery
+                    jq = jq.add(@_jquery)
+                    if @parent is that.builder
+                        that.template.jquery = jq
+                        that.template._jquery = jq
+                        @parent.jquery = jq
+                    @parent._jquery = jq
+                else
+                    $root.append(@_jquery)
             else
-                parent = @_jquery_tracker.el
-                done = -> that.animation.push ->
-                    parent = parent?._jquery_tracker?.el
-                    el = el?._jquery_tracker?.el
-                    return unless parent and el
-                    if parent is parent.builder
-                        parent._jquery.parent().append(el._jquery)
-                    else
-                        for e in el._jquery ? []
-                            parent._jquery?.append(e)
-                    # FIXME listen on dom insertion event
-#                     console.error "ready!", el.name, el._jquery_ready
-                    el._jquery_ready?()
-                    el._jquery_ready = yes
-                # delay til end if el is a builder
-                if el is el.builder
-                    el.ready(done)
-                else
-                    done()
+                @parent._jquery?.append(@_jquery)
+            @_jquery_ready?()
+            @_jquery_ready = yes
+            @_jquery_insert = yes
+        el._jquery_insert.replace?(el)
+
+        el._jquery_manip ?= cancelable_and_retrivable_callbacks()
+        el._jquery_done ?= deferred_callbacks()
+        el.ready(el._jquery_done.callback())
+

     onclose: (el) ->
-        el._jquery_tracker ?= {el}
-#         return if removed el
         if el is el.builder
-            el._jquery ?= $()
+            el._jquery ?= $([], el.parent._jquery)
         else
-            el._jquery ?= $(el.toString())
-#         el._jquery.data('dt-jquery', el)
+            el._jquery ?= $(el.toString(), el.parent._jquery)
         release.call el

-        el.on 'newListener', (type) ->
-            return if el._events?[type]?.length # dont bind two times for the same type
-            el._jquery.bind type, ->
-                el.emit type, this, arguments...
-                return # dont return emit result (which is either true or false)
+
+        insertion = el._jquery_insert
+        insertion = el._jquery_replace if insertion is yes
+        if insertion is undefined
+            @onadd(el.parent, el)
+            insertion = el._jquery_insert
+        el.parent?._jquery_done? =>
+            if el.parent is el.parent.builder
+                insertion()
+            else
+                @animation.push(insertion)
+            # if manip left from last time run them
+            insertion?.that?._jquery_manip?.reset()
+            while (cb = insertion?.that?._jquery_manip?.callbacks.shift())?
+                @animation.push(cb)
+
+    onreplace: (oldtag, newtag) ->
+        newtag._jquery_insert ?= oldtag._jquery_insert
+        oldtag._jquery_insert = null
+
+        if newtag._jquery_insert is true
+            newtag._jquery_replace ?= oldtag._jquery_replace
+            noreplacerequest = newtag._jquery_replace?
+            newtag._jquery_replace ?= singlton_callback newtag, ->
+                return if removed this
+                _jquery = @_jquery ? this
+#                 return unless _jquery?.length
+                oldtag._jquery.replaceWith(_jquery)
+                # replaceWith isnt inplace
+                @_jquery = _jquery
+                if this is @builder
+                    @jquery = _jquery
+            oldtag._jquery_replace = null
+            replace = newtag._jquery_replace
+            replace.replace?(newtag)
+        else
+            newtag._jquery_insert.replace?(newtag)
+
+        newtag._jquery_manip ?= cancelable_and_retrivable_callbacks()
+        oldtag._jquery_manip?.cancel?()
+        newtag._jquery_manip.reset()
+        unless newtag.closed
+            # if manip left from last time run them
+            while (cb = newtag._jquery_manip.callbacks.shift())?
+                @animation.push(cb)
+
+        newtag._jquery_done ?= oldtag._jquery_done
+        newtag._jquery_done ?= deferred_callbacks()
+        oldtag._jquery_done = null
+        cb = newtag._jquery_done.callback()
+        if newtag is newtag.builder
+            cb()
+        else unless newtag.closed
+            newtag.ready(cb)
+        if (newtag._jquery_insert is true and newtag.closed) or noreplacerequest
+            @onclose(newtag)
+        # else just throw cb away, but reset allowed callback

     ontext: (el, text) ->
-        delay.call el, ->
-            @_jquery.text(text)
+        that = this
+        delay.call el, ->
+            that.animation.push @_jquery_manip =>
+                @_jquery.text(text)

     onraw: (el, html) ->
         that = this
         delay.call el, ->
-            that.animation.push =>
+            that.animation.push @_jquery_manip =>
                 @_jquery?.html(html)

+    onattr: (el, key, value) ->
+        that = this
+        delay.call el, ->
+            that.animation.push @_jquery_manip =>
+                if value is undefined
+                    @_jquery.removeAttr(key)
+                else
+                    @_jquery.attr(key, value)
+
     onshow: (el) ->
         delay.call el, ->
             @_jquery.show()
@@ -159,38 +271,13 @@
     onhide: (el) ->
         delay.call el, ->
             @_jquery.hide()
-
-    onattr: (el, key, value) ->
-        delay.call el, ->
-            if value is undefined
-                @_jquery.removeAttr(key)
-            else
-                @_jquery.attr(key, value)
-
-    onreplace: (oldtag, newtag) ->
-        newtag._jquery_tracker ?= el:newtag
-        oldtag._jquery_tracker.el = newtag
-        that = this
-        delay.call oldtag, ->
-            newtag = newtag._jquery_tracker.el
-            delay.call newtag, ->
-                that.animation.push =>
-                    newtag = @_jquery_tracker.el
-                    return if removed(oldtag) or removed(newtag)
-                    _jquery = newtag._jquery ? newtag
-                    return unless _jquery?.length > 0
-                    oldtag._jquery.replaceWith(_jquery)
-                    # replaceWith isnt inplace
-                    for tag in [oldtag, newtag]
-                        tag._jquery = _jquery
-                        if tag is tag.builder
-                            tag.jquery = _jquery

     onremove: (el) ->
         if el._jquery?
             el._jquery.remove()
+            el._jquery_manip?.cancel()
+            delete el._jquery_manip
             delete el._jquery
-        delete el._jquery_tracker

     onend: () ->
 #         @builder._jquery.data('dt-jquery', @template.xml)


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/game_over.coffee
+++ src/game_over.coffee
@@ -15,7 +15,7 @@
 ###

 ###*
-Draws
+Draws Game Over screen and rese

 @name overlay
 @methodOf GameOver#


Check that user can read a project on entities-json route

--- services/web/app/coffee/router.coffee
+++ services/web/app/coffee/router.coffee
@@ -120,7 +120,9 @@
 		privateApiRouter.get  '/user/:user_id/personal_info', AuthenticationController.httpAuth, UserInfoController.getPersonalInfo

 		webRouter.get  '/user/projects', AuthenticationController.requireLogin(), ProjectController.userProjectsJson
-		webRouter.get  '/project/:Project_id/entities', AuthenticationController.requireLogin(), ProjectController.projectEntitiesJson
+		webRouter.get  '/project/:Project_id/entities', AuthenticationController.requireLogin(),
+			AuthorizationMiddlewear.ensureUserCanReadProject
+			ProjectController.projectEntitiesJson

 		webRouter.get  '/project', AuthenticationController.requireLogin(), ProjectController.projectListPage
 		webRouter.post '/project/new', AuthenticationController.requireLogin(), ProjectController.newProject


Fix geocoder page size parameter.

Fix geocoder page size parameter.

--- src/geocoding.coffee
+++ src/geocoding.coffee
@@ -100,14 +100,13 @@
                 @street.translatedName = (
                     @street.name[p13n.getLanguage()] or @street.name.fi
                 ).toLowerCase()
-                @street.addresses = new models.AddressList()
+                @street.addresses = new models.AddressList [], pageSize: 200
                 @street.addresses.comparator = (x) =>
                     parseInt x.get('number')
                 @street.addressesFetched = false
                 @street.addresses.fetch
                     data:
                         street: @street.id
-                        page_size: 200
                     success: =>
                         @street.addressesFetched = true
                         deferred.resolve()


check for key existence before returning

--- src/god/world.coffee
+++ src/god/world.coffee
@@ -50,7 +50,10 @@
     @doc.put(key, value)

   get_local: (key) ->
-    @doc.get(key)
+    if @has_local(key) then @doc.get(key) else null
+
+  has_local: (key) ->
+    @doc.has key

   # TODO: make @up a list
   get_raw: (key, world) ->


Skip new assertions if atom.keymaps.build is not present

--- spec/installed-package-view-spec.coffee
+++ spec/installed-package-view-spec.coffee
@@ -92,15 +92,17 @@
         expect(card.refs.keybindingToggle.checked).toBe false
         expect(_.include(atom.config.get('core.packagesWithKeymapsDisabled') ? [], 'language-test')).toBe true

-        keybindingRows = card.element.querySelectorAll('.package-keymap-table tbody.text-subtle tr')
-        expect(keybindingRows.length).toBe 1
+        if atom.keymaps.build?
+          keybindingRows = card.element.querySelectorAll('.package-keymap-table tbody.text-subtle tr')
+          expect(keybindingRows.length).toBe 1

         card.refs.keybindingToggle.click()
         expect(card.refs.keybindingToggle.checked).toBe true
         expect(_.include(atom.config.get('core.packagesWithKeymapsDisabled') ? [], 'language-test')).toBe false

-        keybindingRows = card.element.querySelectorAll('.package-keymap-table tbody tr')
-        expect(keybindingRows.length).toBe 1
+        if atom.keymaps.build?
+          keybindingRows = card.element.querySelectorAll('.package-keymap-table tbody tr')
+          expect(keybindingRows.length).toBe 1

   describe "when a keybinding is copied", ->
     [pack, card] = []


config: use the test server

config: use the test server

--- src/js/config.coffee
+++ src/js/config.coffee
@@ -1,7 +1,7 @@
 Settings = require('settings')

 config =
-  BASE_SERVER_URL: 'https://pebbleshows.herokuapp.com'
+  BASE_SERVER_URL: 'https://pebbleshows-test.herokuapp.com'
   TRAKT_CLIENT_ID: '16fc8c04f10ebdf6074611891c7ce2727b4fcae3d2ab2df177625989543085e9'
   LOG_SERVER: 'http://pebbleshows-logserver.herokuapp.com'
   SUPPORT_EMAIL: "#{'you'}#{'tux'}#{'@gm'}#{'ail.'}#{'com'}"


fix typo

fix typo

--- src/js/player.coffee
+++ src/js/player.coffee
@@ -31,7 +31,7 @@
          *

          *

          *    mode
-         *    默认值: 'loop'。加入播放器的歌曲列表的播放顺序逻辑，可选值为 'loop'（循环播放），'list'（列表播放，该列表播放到最后一首或第一首后则停止播放），'single'（单曲播放），'random'（单曲随机），'list-random'（列表随机，与random的区别是保证已随机过的列表中歌曲均播放一次后，再对列表随机重置）。
+         *    默认值: 'loop'。加入播放器的歌曲列表的播放顺序逻辑，可选值为 'loop'（循环播放），'list'（列表播放，该列表播放到最后一首或第一首后则停止播放），'single'（单曲播放），'random'（随机），'list-random'（列表随机，与random的区别是保证已随机过的列表中歌曲均播放一次后，再对列表随机重置）。
          *

          *

          *    mute


Update view spec

Update view spec

--- spec/deprecation-cop-view-spec.coffee
+++ spec/deprecation-cop-view-spec.coffee
@@ -1,6 +1,21 @@
+{WorkspaceView} = require 'atom'
+Grim = require 'grim'
 DeprecationCopView = require '../lib/deprecation-cop-view'
-{WorkspaceView} = require 'atom'

 describe "DeprecationCopView", ->
-  it "has one valid test", ->
-    expect("life").toBe "easy"
+  [deprecatedMethod, activationPromise] = []
+
+  beforeEach ->
+    atom.workspaceView = new WorkspaceView
+    activationPromise = atom.packages.activatePackage('deprecation-cop')
+    deprecatedMethod = -> Grim.deprecate("This isn't used")
+    deprecatedMethod()
+    atom.workspaceView.trigger 'deprecation-cop:view'
+
+    waitsForPromise ->
+      activationPromise
+
+  it "displays deprecated methods", ->
+    timeCopView = atom.workspace.getActivePane().getActiveItem()
+    expect(timeCopView.html()).toMatch /deprecation-cop package/
+    expect(timeCopView.html()).toMatch /This isn't used/


:new: Implement All SSH Funcs

:new: Implement All SSH Funcs

--- Source/SSH.coffee
+++ Source/SSH.coffee
@@ -1,6 +1,5 @@

-# Compiler-Output "../Dist/SSH.js"
 FS = require 'fs'
 Driver = require 'ssh2'
 Promise = require 'a-promise'
@@ -18,5 +17,89 @@
     Config.port = Config.port || 2
     @Connected = false
     @Connection = new Driver()
-
+  connect:->
+    return new Promise (Resolve, Reject)=>
+      try
+        @Connection.on 'error', Reject
+        @Connection.on 'ready', =>
+          @Connected = true
+          Resolve()
+        @Connection.connect(@Config)
+      catch error
+        Reject error
+  mkdir:(Path)->
+    return new @exec("mkdir -p #{Path}")
+  exec:(Command, Opts)->
+    throw new Error("Please connect before doing anything else") unless @Connected
+    Opts = Opts || {}
+    return new Promise (Resolve, Reject)=>
+      Command = "cd #{Opts.cwd}; #{Command}" if Opts.cwd
+      @Connection.exec Command, (Error, Stream)=>
+        return Reject(Error) if Error
+        ToReturn = stdout: [], stderr: []
+        Stream.on('close', ->
+          ToReturn.stdout = ToReturn.stdout.join("");
+          ToReturn.stderr = ToReturn.stderr.join("");
+          Resolve ToReturn
+        ).on('data', (Data)->
+          ToReturn.stdout.push Data.toString()
+        ).stderr.on('data', (Data)->
+          ToReturn.stderr.push Data.toString()
+        )
+  put:(LocalFile, RemoteFile, SFTP, Retry = true)->
+    throw new Error("Please connect before doing anything else") unless @Connected
+    return new Promise (Resolve, Reject)=>
+      try
+        FS.access(LocalFile, FS.R_OK)
+      catch
+        return Reject("Local File '#{LocalFile}' doesn't exist")
+      if SFTP
+        ThePromise = Promise.resolve(SFTP)
+      else
+        ThePromise = @requestSFTP()
+      ThePromise.then (SFTP)=>
+        SFTP.fastPut LocalFile, RemoteFile, (Error)=>
+          return Resolve() unless Error
+          return Reject(Error) if Error.message isnt 'No such file' or not Retry
+          @mkdir(RemoteFile.split("/").slice(0,-1).join('/')).then =>
+            @put(LocalFile, RemoteFile, SFTP, false)
+  putMulti:(Files, SFTP)->
+    throw new Error("Please connect before doing anything else") unless @Connected
+    return new Promsie (Resolve, Reject)=>
+      if SFTP
+        ThePromise = Promise.resolve(SFTP)
+      else
+        ThePromise = @requestSFTP()
+      Promises = []
+      ThePromise.then (SFTP)=>
+        Files.forEach (File)=>
+          return unless File.Local or File.Remote
+          return unless FS.existsSync File.Local
+          Promises.push @put(FS.Local, FS.Remote, SFTP)
+        Promise.all(Promises).then(Resolve,Reject);
+  get:(RemoteFile, LocalFile, SFTP)->
+    throw new Error("Please connect before doing anything else") unless @Connected
+    return new Promise (Resolve, Reject)=>
+      if SFTP
+        ThePromise = Promise.resolve(SFTP)
+      else
+        ThePromise = @requestSFTP()
+      ThePromise.then (SFTP)=>
+        Stream = SFTP.createReadStream RemoteFile
+        Contents = []
+        Stream.on('data', (Data)->
+          Contents.push Data.toString()
+        ).on('close', ->
+          Contents = Contents.join('')
+          return Resolve(Contents) unless LocalFile
+          FS.writeFile LocalFile, Contents, (error)->
+            return Reject(error) if error
+            Resolve()
+        )
+  requestSFTP:->
+    throw new Error("Please connect before doing anything else") unless @Connected
+    return new Promise (Resolve, Reject)=>
+      @Connection.sftp (Error, SFTP)=>
+        return Reject(Error) if Error
+        Resolve(SFTP);
 module.exports = SSH


benchmark comment

benchmark comment

--- benchmarks/analysis/logdata_extractor.coffee
+++ benchmarks/analysis/logdata_extractor.coffee
@@ -474,7 +474,7 @@

     aggregate: ()->
         # records that are in the range of current
-        # aggregate time window
+        # aggregate time window, from multiple data files
         inRangeRecords = []
         # hold previous records from those data files that do
         # not have inRangeRecords
@@ -492,7 +492,7 @@
                     #{@startTime} #{@endTime}")
                 dataFileBuffer.read()
                 record = dataFileBuffer.peek()
-            # only take one record for one data file
+            # for one data file only pick last one record in the time range
             inRangeRecord = null
             while @inRange(record)
                 inRangeRecord = dataFileBuffer.read()


Disable default events

Disable default events

--- lib/archive-editor-view.coffee
+++ lib/archive-editor-view.coffee
@@ -18,7 +18,8 @@
           @ol outlet: 'tree', class: 'archive-tree padded list-tree has-collapsable-children'

   initialize: (editor) ->
-    super
+    commandDisposable = super()
+    commandDisposable.dispose()

     @setModel(editor)


discourse

discourse

--- lib/connection/messages.coffee
+++ lib/connection/messages.coffee
@@ -11,7 +11,7 @@
         Go to the Packages → Julia → Open Terminal menu and
         run `Pkg.add("Atom")` in Julia, then try again.
         If you still see an issue, please report it to:
-            julia-users@googlegroups.com
+            https://discourse.julialang.org/
         """
         dismissable: true


Beautify code.

Beautify code.

--- lib/event-watch-element.coffee
+++ lib/event-watch-element.coffee
@@ -1,5 +1,5 @@
 {CompositeDisposable} = require 'atom'
-{View}  = require 'atom-space-pen-views'
+{View} = require 'atom-space-pen-views'
 CSON = require 'season'
 fs = require 'fs-plus'
 later = require 'later'
@@ -289,6 +289,7 @@
     @hasWarning = @displayEvents()
     @generateTooltipTitle()
     if not wasWarning and @hasWarning
-      @startTimer 1  # 1 minute refresh during warnings
+      # 1 minute refresh during warnings
+      @startTimer 1
     else if wasWarning and not @hasWarning
       @startTimer()


Add missing @ before emit calls

Add missing @ before emit calls

--- src/browser/auto-updater-win32.coffee
+++ src/browser/auto-updater-win32.coffee
@@ -32,20 +32,20 @@
   checkForUpdates: ->
     throw new Error('Update URL is not set') unless @updateUrl

-    emit 'checking-for-update'
+    @emit 'checking-for-update'

     updateDotExe = @getUpdateExePath()

     unless fs.existsSync(updateDotExe)
       console.log 'Running developer or Chocolatey version of Atom, skipping'
-      emit 'update-not-available'
+      @emit 'update-not-available'
       return

     args = ['--update', @updateUrl]
     ChildProcess.execFile updateDotExe, args, (error, stdout) =>
       if error?
         console.log "Failed to update: #{error.code} - #{stdout}"
-        emit 'update-not-available'
+        @emit 'update-not-available'
         return

       try
@@ -54,14 +54,14 @@
         latestRelease = JSON.parse(json)?.releasesToApply?.pop?()
       catch error
         console.log "Update output isn't valid: #{stdout}"
-        emit 'update-not-available'
+        @emit 'update-not-available'
         return

       if latestRelease?
-        emit 'update-available'
-        emit 'update-downloaded', {}, latestRelease.releaseNotes, latestRelease.version, new Date(), 'https://atom.io', => @quitAndInstall()
+        @emit 'update-available'
+        @emit 'update-downloaded', {}, latestRelease.releaseNotes, latestRelease.version, new Date(), 'https://atom.io', => @quitAndInstall()
       else
         console.log "You're on the latest version!"
-        emit 'update-not-available'
+        @emit 'update-not-available'

 module.exports = new AutoUpdater()


build plugin: make sure isString before removeFileTrailingSeparator

--- lib/plugin/compile-i18n.coffee
+++ lib/plugin/compile-i18n.coffee
@@ -92,7 +92,10 @@
   str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")

 removeFileTrailingSeparator = (file) ->
-  file.trim().replace RegExp("#{escapeRegExp path.sep}$"), ""
+  if _.isString file
+    file.trim().replace RegExp("#{escapeRegExp path.sep}$"), ""
+  else
+    file

 loadProjectConf = (conf_file=path.join(project_root, 'project-tap.i18n')) ->
   # Returns the project's tap-i18n configuration if tap-i18n is installed


payment: fairly sure this is not meant to be hardcoded

--- client/Main/payment/paymentcontroller.coffee
+++ client/Main/payment/paymentcontroller.coffee
@@ -98,7 +98,7 @@

       subscription = null
       queue.push =>
-        @fetchSubscriptionsWithPlans tags: ['vm'], (err, [subscription_]) ->
+        @fetchSubscriptionsWithPlans tags: tag, (err, [subscription_]) ->
           subscription = subscription_
           queue.fin()


collaboration: minor cosmetics and removed some unused requires

--- client/ide/lib/views/chat/idechatview.coffee
+++ client/ide/lib/views/chat/idechatview.coffee
@@ -1,17 +1,12 @@
 kd                  = require 'kd'
-KDView              = kd.View
-KDTabView           = kd.TabView
-KDLoaderView        = kd.LoaderView
-KDCustomHTMLView    = kd.CustomHTMLView
-
 CustomLinkView      = require 'app/customlinkview'
-IDEChatMessagePane  = require './idechatmessagepane'
 IDEChatSettingsPane = require './idechatsettingspane'
 envDataProvider     = require 'app/userenvironmentdataprovider'

-socialHelpers = require '../../collaboration/helpers/social'
-
-module.exports = class IDEChatView extends KDTabView
+# refactor notes:
+# no need for a KDTabView here but
+# didnot invest more for the timebeing - SY
+module.exports = class IDEChatView extends kd.TabView

   constructor: (options = {}, data)->

@@ -50,14 +45,14 @@

   createLoader: ->

-    @loaderView = new KDView cssClass: 'loader-view'
+    @loaderView = new kd.View cssClass: 'loader-view'

-    @loaderView.addSubView new KDLoaderView
+    @loaderView.addSubView new kd.LoaderView
       showLoader : yes
       size       :
         width    : 24

-    @loaderView.addSubView new KDCustomHTMLView
+    @loaderView.addSubView new kd.CustomHTMLView
       cssClass : 'label'
       partial  : 'Preparing collaboration'


custom prefix support

custom prefix support

--- lib/runtime/completions.coffee
+++ lib/runtime/completions.coffee
@@ -1,3 +1,5 @@
+# TODO: some caching to minimise data transfer
+
 {client} =   require '../connection'
 modules =    require './modules'
 evaluation = require './evaluation'
@@ -15,13 +17,14 @@
       line: editor.getTextInBufferRange [[row, 0], [row, Infinity]]
       column: column+1

-  toCompletion: (c) ->
+  toCompletion: (c, pre) ->
     if c.constructor is String
-      text: c
-    else
-      c
+      c = text: c
+    if not c.prefix?
+      c.replacementPrefix = pre
+    c

   getSuggestions: (data) ->
     return [] unless client.isConnected()
-    @rawCompletions(data).then (completions) =>
-      completions?.map(@toCompletion) or []
+    @rawCompletions(data).then ({completions, prefix}) =>
+      completions.map((c) => @toCompletion c, prefix)


Corrige evento productAddedToCart

Corrige evento productAddedToCart

--- src/coffee/portal-sku-selector.coffee
+++ src/coffee/portal-sku-selector.coffee
@@ -273,7 +273,7 @@
 				$(window).trigger 'vtex.modal.hide'
 				$.get($.skuSelector.getAddUrlForSku(selectedSku.sku, 1, 1, @productData.salesChannel, false))
 				.done (data) =>
-						@triggerProductEvent 'productAddedToCart'
+						$(window).trigger 'productAddedToCart'
 				.fail (jqXHR, status) =>
 						window.location.href = $.skuSelector.getAddUrlForSku(selectedSku.sku, 1, @productData.salesChannel)
 				return false


Hide legend by default when no subkeys

Hide legend by default when no subkeys

--- muleview/app/view/ChartsView.coffee
+++ muleview/app/view/ChartsView.coffee
@@ -15,8 +15,6 @@
   layout: "border"
   othersKey: Muleview.Settings.othersSubkeyName

-  showLegend: true # default
-
   # Replace full Mule key names as keys with retention-name only
   processAlertsHash: (alerts) ->
     ans = {}
@@ -56,6 +54,8 @@
       dataStore: @stores[@defaultRetention]
     @subkeysStore.loadSubkeys(@subkeys)

+    # Default to hiding the legend if no subkeys exist:
+    @showLegend = @subkeys.length > 0

     # Init component:
     @items = @items()


Use `run_remote_endpoint` for the property name, as the name has significance to the Log Manager

--- src/code/providers/lara-provider.coffee
+++ src/code/providers/lara-provider.coffee
@@ -285,7 +285,7 @@
               documentID: docStore.recordid
               documentUrl: url
             }
-            laraData.remoteEndpoint = existingRunState.run_remote_endpoint if existingRunState?.run_remote_endpoint?
+            laraData.run_remote_endpoint = existingRunState.run_remote_endpoint if existingRunState?.run_remote_endpoint?
             @logLaraData laraData
             processCreateResponse createResponse
             callback null
@@ -405,7 +405,7 @@
           runStateUrl: openSavedParams.url
           documentID: openSavedParams.source
         }
-        laraData.remoteEndpoint = data.run_remote_endpoint if data?.run_remote_endpoint?
+        laraData.run_remote_endpoint = data.run_remote_endpoint if data?.run_remote_endpoint?
         @logLaraData laraData
         processInitialRunState openSavedParams.url, openSavedParams.source, openSavedParams.readOnlyKey, data
       .fail (jqXHR, status, error) ->


register

register

--- src/coffee/directives/controller.coffee
+++ src/coffee/directives/controller.coffee
@@ -7,7 +7,7 @@
 ##

 angular.module('CoolForm').
-  directive('coolform', (definitionService, validatorService) ->
+  directive('coolform', (definitionService, registrationService) ->

     l = (scope, elem, attr) ->

@@ -24,7 +24,8 @@
       scope.$watch('form', (v) ->
         if v? and v.form?
           scope.definition = scope.form.form
-          validatorService(scope)
+          scope.service = registrationService()
+          scope.service.registerController(scope, scope.definition)
       )

     return {


Export subdomain

Export subdomain

--- src/pagerduty.coffee
+++ src/pagerduty.coffee
@@ -136,3 +136,5 @@
         return

       cb(null, json.schedules)
+
+  subdomain: pagerDutySubdomain


refactor(app generator): add build config for filesystem layout

--- generators/app/templates/GruntFile.coffee
+++ generators/app/templates/GruntFile.coffee
@@ -2,6 +2,20 @@
 ##  ====
 ##
 ##  Anatomy of a build:
+##
+##    * The build's filesystem layout
+##        * Source directory:
+##            * src/
+##
+##        * Distribution artifacts' destination directory:
+##            * dist/
+##
+##        * Assembly directories:
+##            * dist/app/   - collects the app's build results
+##            * dist/doc/   - collects the app's code documentation
+##
+##        * Tests directory:
+##            * test/
 ##
 ##  ====
 ##
@@ -33,6 +47,25 @@

         npm:
             grunt.file.readJSON(        'package.json' )
+
+
+        ##
+        ##  Local data as '<%= build.* %>'
+        ##
+
+        build:
+
+            ##
+            ##  Filesystem:
+            ##
+
+            source:                     'src/'
+            dist:                       'dist/'
+            assembly:
+                app:                    '<%= build.dist %>app/'
+                doc:                    '<%= build.dist %>doc/'
+
+            test:                       'test/'

         ##  ------------------------------------------------


mercury is in retrograde

mercury is in retrograde

--- components/filter2/dropdown/test/view.coffee
+++ components/filter2/dropdown/test/view.coffee
@@ -36,6 +36,6 @@
     @view.$('.filter-nav-main-text').text().should.equal 'price'
     @view.$('.filter-nav-active-text').text().should.equal ''
     @view.$('.filter-dropdown-nav > a').first().text().should.equal 'All prices'
-    @view.$('.filter-dropdown-nav > a:nth-child(2) .filter-dropdown-text').text().should.equal 'For Sale'
+    @view.$('.filter-dropdown-nav > a:nth-child(2) .filter-dropdown-text').text().should.equal 'for Sale'
     @view.$('.filter-dropdown-nav > a:nth-child(2) .filter-dropdown-count').text().should.equal '(535)'


Agent pie: test start/end angle in transition

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -112,7 +112,7 @@

         path.transition().duration(750).attrTween('d', (d,i) ->
             #`var i`
-            theOldDataInPie = @oldPieData ? piedata
+            theOldDataInPie = oldPieData ? piedata
             # Interpolate the arcs in data space
             s0 = undefined
             e0 = undefined


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -69,8 +69,8 @@
       arcs.append("svg:text").attr("transform", (d, i) ->
         procent_val = Math.round(data[i].value/sum * 100)
         #d.innerRadius = (radiuso * (100-procent_val)/100) - radiuso/2 #45  #45=max text size/2
-        d.innerRadius = radiuso - 10#i #(radiuso * (100-procent_val)/100) - radiuso/2 #45  #45=max text size/2
-        d.outerRadius = radiuso
+        #d.innerRadius = radiuso - 10#i #(radiuso * (100-procent_val)/100) - radiuso/2 #45  #45=max text size/2
+        #d.outerRadius = radiuso
         "translate(" + arc.centroid(d) + ")")
         .attr('fill', "#fff")
         .attr("text-anchor", "middle").text((d, i) ->


fullpieagent testing

fullpieagent testing

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -283,7 +283,7 @@
             .duration(1500)
             #.attrTween("d", pieTween)
             .attrTween("d", (d,i) ->
-                console.log("d",d)
+                console.log("d",(d) -> d.value)
                 console.log("i",i)
                 i = d3.interpolate({startAngle: 0, endAngle: 0}, {startAngle: d.startAngle, endAngle: d.endAngle})
                 return (t) ->


temporary fix for lists

temporary fix for lists

--- widgets/progress_list/progress_list.coffee
+++ widgets/progress_list/progress_list.coffee
@@ -1,5 +1,6 @@
 class Dashing.ProgressList extends Dashing.Widget
   ready: ->
+    return
     @currentIndex = 1
     @list = new List("#{@get('node').id}",
        valueNames: ["label"]


More refactor

More refactor

--- workers/social/lib/social/models/vm.coffee
+++ workers/social/lib/social/models/vm.coffee
@@ -68,6 +68,19 @@
         default         : no

   @createDomains = (account, domains, hostnameAlias)->
+
+    updateRelationship = (domainObj)->
+      Relationship.one
+        targetName: "JDomain",
+        targetId: domainObj._id,
+        sourceName: "JAccount",
+        sourceId: account._id,
+        as: "owner"
+      , (err, rel)->
+        if err or not rel
+          account.addDomain domainObj, (err)->
+            console.log err  if err?
+
     JDomain = require './domain'
     domains.forEach (domain) ->
       JDomain.assure { domain }, (err, domainObj) ->
@@ -78,22 +91,13 @@
         domainObj.regYears      = 0

         if domainObj.isNew
-          method = domainObj.save
+          domainObj.save (err)->
+            console.log err  if err
+            updateRelationship domainObj
         else
-          method = domainObj.update
-
-        method (err)->
-          console.log err  if err?
-          Relationship.one
-            targetName: "JDomain",
-            targetId: domainObj._id,
-            sourceName: "JAccount",
-            sourceId: account._id,
-            as: "owner"
-          , (err, rel)->
-            if err or not rel
-              account.addDomain domainObj, (err)->
-                console.log err  if err?
+          domainObj.update (err)->
+            console.log err  if err
+            updateRelationship domainObj

   @fixUserDomains = permit 'change bundle',
     success: (client, callback)->


Fetch domains does not require to be owner of that vm.

--- workers/social/lib/social/models/vm.coffee
+++ workers/social/lib/social/models/vm.coffee
@@ -320,7 +320,7 @@

         selector =
           hostnameAlias : hostnameAlias
-          users         : { $elemMatch: id: user.getId(), owner: yes }
+          users         : { $elemMatch: id: user.getId() }

         JVM.one selector, {hostnameAlias:1}, (err, vm)->
           return callback err, []  if err or not vm


fix broken parsing of RE

fix broken parsing of RE

--- library/membrane/duplex.coffee
+++ library/membrane/duplex.coffee
@@ -206,7 +206,7 @@
     # Pay attention that most implementations side effect the context.
     prelude: (symbol, context, request, next) ->
         encrypted = request.connection.encrypted
-        pure = /[a-zA-Z0-9/-_]+/.test @location()
+        pure = /[a-zA-Z0-9\/-_]+/.test @location()
         assert pure, "location is not pure enough"
         proto = request.headers["x-forwarded-proto"]
         enc = encrypted or proto is "https" and yes
@@ -333,7 +333,7 @@
     # is asynchronously wired in, so consult with `async` package.
     # Please be sure invoke the `next` arg to proceed, if relevant.
     register: (kernel, router, next) ->
-        pure = /[a-zA-Z0-9/-_]+/.test @location()
+        pure = /[a-zA-Z0-9\/-_]+/.test @location()
         resolve = (handler) => try handler.of @location()
         assert pure, "service location is not pure enough"
         assert sserver = kernel.serverSocket, "no HTTP socket"
@@ -358,7 +358,7 @@
     # is asynchronously wired in, so consult with `async` package.
     # Please be sure invoke the `next` arg to proceed, if relevant.
     unregister: (kernel, router, next) ->
-        pure = /[a-zA-Z0-9/-_]+/.test @location()
+        pure = /[a-zA-Z0-9\/-_]+/.test @location()
         resolve = (handler) => try handler.of @location()
         assert pure, "service location is not pure enough"
         assert sserver = kernel.serverSocket, "no HTTP socket"


surgery ops to the old coding

surgery ops to the old coding

--- library/nucleus/restful.coffee
+++ library/nucleus/restful.coffee
@@ -123,10 +123,10 @@
     # idempotent. Please refer to the implementation of this method
     # and to the implementation of the `Duplex` for the information.
     @spinoff: (implement) -> (request, response, signed) ->
-        message = "Spinned off HTTP request at %s"
         noImplement = "no valid implementation body"
         assert _.isFunction(implement), noImplement
         assert _.isArguments capture = arguments or 0
+        m = "Spinned off incoming HTTP request at %s"
         shadow = request.shadow or Object.create this
         execute = -> implement.apply shadow, capture
         return execute() if _.isObject request.shadow
@@ -138,7 +138,7 @@
         e = get: -> try request[symbol] or undefined
         {AccessGate} = require "../exposure/access"
         symbol = try AccessGate.ACCESS_ENTITY_SYMBOL
-        logger.debug message.grey, try request.url
+        logger.debug m.grey, request.url?.underline
         Object.defineProperty shadow, "session", s
         Object.defineProperty shadow, symbol, e
         @emit "spinoff", capture...; execute()


Check in the implementation of the conditional services

--- library/nucleus/restful.coffee
+++ library/nucleus/restful.coffee
@@ -26,7 +26,8 @@
 url = require "url"
 http = require "http"
 util = require "util"
-events = require "eventemitter2"
+async = require "async"
+assert = require "assert"
 colors = require "colors"
 logger = require "winston"

@@ -56,6 +57,27 @@
     # override it and provie support for more methods, up to you.
     @SUPPORTED = ["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"]

+    # Impose a conditional limitation on the service. The limiation
+    # will be invoked when a router is determining whether a service
+    # matches the condition or not. The limitation has to either do
+    # accept or decline. Do this by calling `decide` with a boolean!
+    # Especially useful for service with the same resource but with
+    # different conditions, such as mobile only and desktop only.
+    @condition: (synopsis, limitation) ->
+        return @$condition if arguments.length is 0
+        limitation = _.find arguments, _.isFunction
+        generic = "service condition: #{limitation}"
+        synopsis = generic unless _.isString synopsis
+        noLimitation = "a limitation has to be function"
+        wrongSignature = "malformed limitation signature"
+        assert _.isString(synopsis), "got no synopsis"
+        assert _.isFunction(limitation), noLimitation
+        assert limitation.length is 3, wrongSignature
+        assert _.isArray inherted = @$condition or []
+        @$condition = inherted.concat
+            limitation: limitation
+            synopsis: synopsis
+
     # This method is intended for indicating to a client that the
     # method that has been used to make the request is not supported
     # by this service of the internals that are comprising service.
@@ -70,6 +92,24 @@
         @emit "unsupported", request, response, next
         return response.send descriptor if doesJson
         response.send message; this
+
+    # This method determines whether the supplied HTTP request
+    # matches this service. This is determined by examining the
+    # domain/host and the path, in accordance with the patterns
+    # that were used for configuring the class of this service.
+    # It is async, so be sure to call the `decide` with boolean!
+    matches: (request, response, decide) ->
+        conditions = @constructor.condition?()
+        conditions = [] unless _.isArray conditions
+        identify = @constructor?.identify().underline
+        p = (i, c) -> i.limitation request, response, c
+        fails = "service #{identify} fails some conditions"
+        super request, response, (decision) =>
+            return decide no unless decision
+            async.every conditions, p, (confirms) ->
+                return decide yes if confirms
+                logger.debug fails.yellow
+                decide no; return this

     # Process the already macted HTTP request according to the REST
     # specification. That is, see if the request method conforms to


fix a syntactic error

fix a syntactic error

--- library/nucleus/routing.coffee
+++ library/nucleus/routing.coffee
@@ -117,7 +117,7 @@
     # It will also call hooks on the service, notifying unregister.
     unregister: (routable, callback) ->
         noClass = "broken routable: #{routable}"
-        assert try routable.constructor, noClass
+        assert routable.constructor or 0, noClass
         identify = routable.constructor.identify()
         inspected = identify.toString().underline
         noRegistry = "Could not access the registry"


Fix one more typo

Fix one more typo

--- library/visualize/trees.coffee
+++ library/visualize/trees.coffee
@@ -161,7 +161,7 @@
     resolve: (tag) ->
         correct = _.isString tag
         return this if @tag is tag
-        invalid "The supplied node is not string"
+        invalid "The supplied tag is not string"
         throw new Error invalid unless correct
         for index, node in (@children or [])
             return node if node.tag is tag


movable

movable

--- src/rotatable.coffee
+++ src/rotatable.coffee
@@ -24,7 +24,7 @@
 => 0.09817477042468103 # 2 * (Math.PI / 64)
 </pre></code>

-@name Movable
+@name Rotatable
 @module
 @constructor


:racehorse: Compare markers instead of ranges in Selection

This largely reduces the overhead of converting ranges and points from native to
javascript objects.

--- src/selection.coffee
+++ src/selection.coffee
@@ -755,7 +755,7 @@
   #
   # * `otherSelection` A {Selection} to compare against
   compare: (otherSelection) ->
-    @getBufferRange().compare(otherSelection.getBufferRange())
+    @marker.compare(otherSelection.marker)

   ###
   Section: Private Utilities


tokenizer: fix not capturing all output

tokenizer: fix not capturing all output

--- src/tokenizer.coffee
+++ src/tokenizer.coffee
@@ -22,7 +22,7 @@
                 continue
             break
         tokens.push(identify(source.slice(next + BEGIN.length, end)))
-        start = end + END.length + 1
+        start = end + END.length
         if start >= source.length
             break
     return tokens


Fix map to use new calling style

Fix map to use new calling style

--- src/ubret/map.coffee
+++ src/ubret/map.coffee
@@ -1,6 +1,4 @@
-BaseTool = window.Ubret.BaseTool or require('./base_tool')
-
-class Map extends BaseTool
+class Map extends Ubret.BaseTool
   name: 'Map'

   # Set the default image path for Leaflet
@@ -20,8 +18,8 @@
       iconAnchor: [13, 41]
     }

-  constructor: (opts) ->
-    super opts
+  constructor: (selector) ->
+    super
     @circles = []
     @limit = @limit or 30

@@ -90,32 +88,11 @@
     @circles.push circle

   plotObjects: =>
-    data = @dimensions.uid.top(@limit)
     @map.removeLayer(marker) for marker in @circles
     @circles = new Array
-    @plotObject subject for subject in data
+    @plotObject subject for subject in @opts.data

     latlng = new L.LatLng(data[0].dec, data[0].ra)
     @map.panTo latlng
-
-  selected: (itemId) =>
-    item = _.find @data, (subject) ->
-      subject.zooniverse_id = itemId
-    latlng = new L.LatLng(item.dec, item.ra)
-    circle = (c for c in @circles when c.zooniverse_id is itemId)[0]
-    @selectSubject circle
-
-  # Events
-  selectSubject: (circle) =>
-    # Set previous selected subject back to default icon
-    if @selected_subject?
-      @selected_subject.setIcon @default_icon
-
-    @selected_subject = circle
-    circle.openPopup()
-    circle.setIcon @selected_icon

-if typeof require is 'function' and typeof module is 'object' and typeof exports is 'object'
-  module.exports = Map
-else
-  window.Ubret['Map'] = Map+window.Ubret.Map = Map


Use the right project path for document title

--- src/workspace.coffee
+++ src/workspace.coffee
@@ -159,16 +159,24 @@
   # open.
   updateWindowTitle: =>
     appName = 'Atom'
-    if projectPath = atom.project?.getPaths()[0]
-      if item = @getActivePaneItem()
-        document.title = "#{item.getTitle?() ? 'untitled'} - #{projectPath} - #{appName}"
-        atom.setRepresentedFilename(item.getPath?() ? projectPath)
-      else
-        document.title = "#{projectPath} - #{appName}"
-        atom.setRepresentedFilename(projectPath)
+    projectPaths = atom.project?.getPaths() ? []
+    if item = @getActivePaneItem()
+      itemPath = item.getPath?()
+      itemTitle = item.getTitle?()
+      projectPath = _.find projectPaths, (projectPath) ->
+        itemPath is projectPath or itemPath?.startsWith(projectPath + path.sep)
+    itemTitle ?= "untitled"
+    projectPath ?= projectPaths[0]
+
+    if item? and projectPath?
+      document.title = "#{itemTitle} - #{projectPath} - #{appName}"
+      atom.setRepresentedFilename(itemPath ? projectPath)
+    else if projectPath?
+      document.title = "#{projectPath} - #{appName}"
+      atom.setRepresentedFilename(projectPath)
     else
-      document.title = "untitled - #{appName}"
-      atom.setRepresentedFilename('')
+      document.title = "#{itemTitle} - #{appName}"
+      atom.setRepresentedFilename("")

   # On OS X, fades the application window's proxy icon when the current file
   # has been modified.


reduce snapshot interval length

reduce snapshot interval length

--- src/smc-util/syncstring_schema.coffee
+++ src/smc-util/syncstring_schema.coffee
@@ -84,7 +84,7 @@
                 string_id         : (obj, db) -> db.sha1(obj.project_id, obj.path)
                 users             : null
                 last_snapshot     : null
-                snapshot_interval : 1000
+                snapshot_interval : 400
                 project_id        : null
                 path              : null
                 deleted           : null


use mock engine everywhere

use mock engine everywhere

--- js/src/auth/SearchCredentialService.coffee
+++ js/src/auth/SearchCredentialService.coffee
@@ -4,22 +4,22 @@
   'bluebird'
   'kryptnostic.logger'
   'kryptnostic.authentication-stage'
-  'kryptnostic.kryptnostic-engine'
+  'kryptnostic.mock.kryptnostic-engine'
   'kryptnostic.rsa-crypto-service'
   'kryptnostic.crypto-key-storage-api'
   'kryptnostic.credential-loader'
   'kryptnostic.search-key-serializer'
 ], (require) ->

-  _                   = require 'lodash'
-  Promise             = require 'bluebird'
-  Logger              = require 'kryptnostic.logger'
-  AuthenticationStage = require 'kryptnostic.authentication-stage'
-  CredentialLoader    = require 'kryptnostic.credential-loader'
-  RsaCryptoService    = require 'kryptnostic.rsa-crypto-service'
-  CryptoKeyStorageApi = require 'kryptnostic.crypto-key-storage-api'
-  KryptnosticEngine   = require 'kryptnostic.kryptnostic-engine'
-  SearchKeySerializer = require 'kryptnostic.search-key-serializer'
+  _                     = require 'lodash'
+  Promise               = require 'bluebird'
+  Logger                = require 'kryptnostic.logger'
+  AuthenticationStage   = require 'kryptnostic.authentication-stage'
+  CredentialLoader      = require 'kryptnostic.credential-loader'
+  RsaCryptoService      = require 'kryptnostic.rsa-crypto-service'
+  CryptoKeyStorageApi   = require 'kryptnostic.crypto-key-storage-api'
+  MockKryptnosticEngine = require 'kryptnostic.mock.kryptnostic-engine'
+  SearchKeySerializer   = require 'kryptnostic.search-key-serializer'

   log = Logger.get('SearchCredentialService')

@@ -66,7 +66,7 @@
     constructor: ->
       @credentialLoader    = new CredentialLoader()
       @cryptoKeyStorageApi = new CryptoKeyStorageApi()
-      @engine              = new KryptnosticEngine()
+      @engine              = new MockKryptnosticEngine()
       @searchKeySerializer = new SearchKeySerializer()

     getFhePrivateKey: ( notifier = -> ) ->


Server: serve campaign if active

Server: serve campaign if active

--- workers/social/lib/social/render/loggedout/kodinghome.coffee
+++ workers/social/lib/social/render/loggedout/kodinghome.coffee
@@ -12,7 +12,7 @@
   userAccount   = JSON.stringify account
   campaignStats = null

-  prepareHTML = ->
+  prepareHTML = (site)->
     """
     <!doctype html>
     <html lang="en">
@@ -26,19 +26,19 @@
       <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1" />
       <link rel="shortcut icon" href="/a/images/favicon.ico" />
       <link rel="fluid-icon" href="/a/images/logos/fluid512.png" title="Koding" />
-      <link rel="stylesheet" href="/a/site.#{campaign}/css/kd.css?#{KONFIG.version}" />
-      <link rel="stylesheet" href="/a/site.#{campaign}/css/main.css?#{KONFIG.version}" />
+      <link rel="stylesheet" href="/a/site.#{site}/css/kd.css?#{KONFIG.version}" />
+      <link rel="stylesheet" href="/a/site.#{site}/css/main.css?#{KONFIG.version}" />
     </head>
     <body class='home'>

       <!--[if IE]><script>(function(){window.location.href='/unsupported.html'})();</script><![endif]-->

-      <script src="/a/site.#{campaign}/js/libs.js?#{KONFIG.version}"></script>
-      <script src="/a/site.#{campaign}/js/kd.libs.js?#{KONFIG.version}"></script>
-      <script src="/a/site.#{campaign}/js/kd.js?#{KONFIG.version}"></script>
+      <script src="/a/site.#{site}/js/libs.js?#{KONFIG.version}"></script>
+      <script src="/a/site.#{site}/js/kd.libs.js?#{KONFIG.version}"></script>
+      <script src="/a/site.#{site}/js/kd.js?#{KONFIG.version}"></script>
       <script>KD.userAccount=#{userAccount}</script>
       <script>KD.campaignStats=#{campaignStats}</script>
-      <script src="/a/site.#{campaign}/js/main.js?#{KONFIG.version}"></script>
+      <script src="/a/site.#{site}/js/main.js?#{KONFIG.version}"></script>

       <!-- SEGMENT.IO -->
       <script type="text/javascript">
@@ -71,12 +71,13 @@
     when 'hackathon'
       bongoModels.JWFGH.getStats account, (err, stats) ->

-        console.log err  if err
+        callback null, prepareHTML 'landing'  if err

         campaignStats = JSON.stringify stats
-        callback null, prepareHTML()
+        callback null, prepareHTML 'hackathon'
+
     else
-      callback null, prepareHTML()
+      callback null, prepareHTML 'landing'


updating project-scaffolding questions

updating project-scaffolding questions

--- src/toaster/generators/project.coffee
+++ src/toaster/generators/project.coffee
@@ -29,14 +29,10 @@
 		if name? && src? && release?
 			return @scaffold target, name, src, release

-		log "#{'Let\'s toast something fresh! :)'.grey.bold}"
-		log ". With this as your basepath: #{target.cyan}"
-		log ". Please tell me:"
-
-		q1 = "\tWhere do you want your src folder? [src] : "
-		q2 = "\tWhere do you want your release file? [www/js/app.js] : "
-		q3 = "\tStarting from your webroot '/', what's the folderpath to "+
-			 "reach your release file? (i.e. javascript) (optional) : "
+		q1 = "Path to your src folder? [src] : "
+		q2 = "Path to your release file? [www/js/app.js] : "
+		q3 = "Starting from your webroot '/', what's the folderpath to "+
+			 "reach your release file? (i.e. js) (optional) : "

 		@ask q1.magenta, /.*/, (src = null)=>
 			@ask q2.magenta, /.*/, (release = null)=>
@@ -57,7 +53,7 @@
 		vendorsdir = pn "#{target}/vendors"
 		releasefile = pn "#{target}/#{release}"
 		releasedir = releasefile.split("/").slice(0, -1).join "/"
-
+
 		log "#{'Created'.green.bold} #{target}" if FsUtil.mkdir_p target
 		log "#{'Created'.green.bold} #{srcdir}" if FsUtil.mkdir_p srcdir
 		log "#{'Created'.green.bold} #{vendorsdir}" if FsUtil.mkdir_p vendorsdir


update route generation

update route generation

--- BackofficeBundle/Resources/public/coffee/page/nodeView.coffee
+++ BackofficeBundle/Resources/public/coffee/page/nodeView.coffee
@@ -150,7 +150,12 @@
     )

   changeVersion: (event) ->
-    Backbone.history.navigate('#node/show/' + @node.get('node_id') + '/' + @language + '/' + event.currentTarget.value, {trigger: true})
+    redirectRoute = appRouter.generateUrl('showNodeWithLanguageAndVersion',
+      nodeId: @node.get('node_id'),
+      language: @language,
+      version: event.currentTarget.value
+    )
+    Backbone.history.navigate(redirectRoute , {trigger: true})
     return

   addLanguagesToView: ->
@@ -174,7 +179,11 @@
     )

   changeLanguage: (event) ->
-    Backbone.history.navigate('#node/show/' + @node.get('node_id') + '/' + $(event.currentTarget).data('language'), {trigger: true})
+    redirectRoute = appRouter.generateUrl('showNodeWithLanguage',
+      nodeId: @node.get('node_id'),
+      language: $(event.currentTarget).data('language')
+    )
+    Backbone.history.navigate(redirectRoute , {trigger: true})

   addPreviewLink: ->
     previewLink = @node.get('links')._self_preview


Delete conf.coffee

Delete conf.coffee

--- server/coffee/conf.coffee
+++ server/coffee/conf.coffee
@@ -1,14 +0,0 @@
-module.exports =
-  appName: 'prototype'
-  debugPort: 3017
-  elasticsearch:
-    host: 'localhost:9200'
-    index: 'users'
-  smtp:
-    host: 'mail.your-server.de'
-    secure: true
-    auth:
-      user: 'webmaster@suncom.de'
-      pass: '3#1k*kP=dVx'
-  appEmail: 'protothril@sun.com.py'
-  frontend: 'localhost:9000/?'


Only show "add favorite" button when signed in.

--- scripts/src/controllers/Classifier.coffee
+++ scripts/src/controllers/Classifier.coffee
@@ -52,6 +52,7 @@
       '.species .other-creatures [value="yes"]': 'otherYes'
       '.species .other-creatures [value="no"]': 'otherNo'
       '.species .finished': 'speciesFinishedButton'
+      '.summary .favorite': 'favoriteButton'
       '.summary .map-toggle .thumbnail img': 'imageThumbnail'
       '.summary .map-toggle .map img': 'mapThumbnail'

@@ -75,6 +76,12 @@
         @groundCoverList.append """

<button value="#{id}">#{description}</button>

         """
+
+      User.bind 'sign-in', =>
+        if User.current?
+          @favoriteButton.css display: ''
+        else
+          @favoriteButton.css display: 'none'

     reset: =>
       super


Server-side method for updating publication title.

--- server/publication.coffee
+++ server/publication.coffee
@@ -394,6 +394,26 @@
         library:
           _id: publication._id

+  # TODO: Use this code on the client side as well
+  'publication-set-title': (publicationId, title) ->
+    check publicationId, DocumentId
+    check title, NonEmptyString
+
+    person = Meteor.person()
+    throw new Meteor.Error 401, "User not signed in." unless person
+
+    publication = Publication.documents.findOne Publication.requireReadAccessSelector(person,
+      _id: publicationId
+    )
+    throw new Meteor.Error 400, "Invalid publication." unless publication
+
+    Publication.documents.update Publication.requireMaintainerAccessSelector(person,
+      _id: publication._id
+    ),
+      $set:
+        updatedAt: moment.utc().toDate()
+        title: title
+
 Meteor.publish 'publications-by-author-slug', (slug) ->
   check slug, NonEmptyString


feat: adding auth as query param

feat: adding auth as query param

--- api/server.coffee
+++ api/server.coffee
@@ -2,21 +2,23 @@
 Firebase = require('firebase')
 table = new Firebase('https://thetable.firebaseio.com/')

-mytoken = require("./private-token")
-
-FirebaseTokenGenerator = require("firebase-token-generator")
-tokenGenerator = new FirebaseTokenGenerator(mytoken)
-token = tokenGenerator.createToken({name: "table-api"}, {admin: true})
-
-table.auth(token, (error) ->
-  if(error)
-    console.log("failed to auth", error)
-   else
-    console.log("authed.")
-)
+auth = (req) ->
+  mytoken = req.params.token
+  if mytoken == "" or mytoken is null or mytoken is undefined
+   return false
+  FirebaseTokenGenerator = require("firebase-token-generator")
+  tokenGenerator = new FirebaseTokenGenerator(mytoken)
+  token = tokenGenerator.createToken({name: "table-api"})
+  table.auth(token, (error) ->
+    if(error)
+      console.log("failed to auth", error)
+    else
+      console.log("authed.")
+  )

 app = express()
-app.get "/match", (req, res) ->
+app.get "/:token/match", (req, res) ->
+  auth req
   current = table.child('current_games')
   current.once('value', (nameSnapshot) ->
     game = nameSnapshot.val()
@@ -29,7 +31,8 @@
     ]
   )
   return
-app.get "/match/away", (req, res) ->
+app.get "/:token/match/away", (req, res) ->
+  auth req
   away = table.child('current_games')
   away.once('value', (nameSnapshot) ->
     game = nameSnapshot.val()
@@ -44,7 +47,8 @@
     )
   )
   return
-app.get "/match/away/add", (req, res) ->
+app.get "/:token/match/away/add", (req, res) ->
+  auth req
   awayAdd = table.child('current_games')
   awayAdd.once('value', (nameSnapshot) ->
     game = nameSnapshot.val()
@@ -59,8 +63,29 @@
     )
   )
   return
-
-app.get "/match/home", (req, res) ->
+app.get "/:token/match/away/sub", (req, res) ->
+  auth req
+  add = table.child('current_games')
+  add.once('value', (nameSnapshot) ->
+    game = nameSnapshot.val()
+    id = Object.keys(game)[0]
+    score = game[id].away_score
+    score = score - 1
+    if score < 0
+      res.send [
+        error: "You can't go negative."
+      ]
+      return
+    game[id].away_score = score
+    add.child(id).set(game[id], =>
+      res.send [
+        away_score: score
+      ]
+    )
+  )
+  return
+app.get "/:token/match/home", (req, res) ->
+  auth req
   home = table.child('current_games')
   home.once('value', (nameSnapshot) ->
     game = nameSnapshot.val()
@@ -76,7 +101,8 @@
   )
   return

-app.get "/match/home/add", (req, res) ->
+app.get "/:token/match/home/add", (req, res) ->
+  auth req
   add = table.child('current_games')
   add.once('value', (nameSnapshot) ->
     game = nameSnapshot.val()
@@ -92,7 +118,8 @@
   )
   return

-app.get "/match/home/sub", (req, res) ->
+app.get "/:token/match/home/sub", (req, res) ->
+  auth req
   add = table.child('current_games')
   add.once('value', (nameSnapshot) ->
     game = nameSnapshot.val()


added checktoken helper functions to testhelper file

--- servers/testhelper.coffee
+++ servers/testhelper.coffee
@@ -110,6 +110,32 @@
       .map (s) -> s.trim().toLowerCase() # clear empty spaces

     return data
+
+
+  @generateCheckTokenRequestBody = (opts = {}) ->
+
+    defaultBodyObject =
+      token :  generateRandomString()
+
+    deepObjectExtend defaultBodyObject, opts
+
+    return defaultBodyObject
+
+
+  @generateCheckTokenRequestParams = (opts = {}) ->
+
+    url  = generateUrl
+      route : '-/teams/validate-token'
+
+    body = TeamHandlerHelper.generateCheckTokenRequestBody()
+
+    params               = { url, body }
+    defaultRequestParams = generateDefaultParams params
+    requestParams        = deepObjectExtend defaultRequestParams, opts
+    # after deep extending object, encodes body param to a query string
+    requestParams.body   = querystring.stringify requestParams.body
+
+    return requestParams

   @generateJoinTeamRequestBody = (opts = {}) ->


added sandstorm

added sandstorm

--- server/configuration/accounts_meld.coffee
+++ server/configuration/accounts_meld.coffee
@@ -1,6 +1,6 @@
 orig_updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService
 Accounts.updateOrCreateUserFromExternalService = (serviceName, serviceData, options) ->
-	if serviceName not in ['facebook', 'github', 'google', 'meteor-developer', 'linkedin', 'twitter'] and serviceData._oAuthCustom isnt true
+	if serviceName not in ['facebook', 'github', 'gitlab', 'google', 'meteor-developer', 'linkedin', 'twitter', 'sandstorm'] and serviceData._oAuthCustom isnt true
 		return

 	if serviceName is 'meteor-developer'


fix indentation in test titles

fix indentation in test titles

--- server/test/units/headline_service.coffee
+++ server/test/units/headline_service.coffee
@@ -12,8 +12,8 @@
 suite('HeadlineService')

 test('.getRecentHeadlines returns the given number of most recent headlines
-  in decending date order with the period end calculated for annual
-  indicator data', (done)->
+ in decending date order with the period end calculated for annual
+ indicator data', (done)->
   indicatorData = [
     {
       "year": 2001,
@@ -83,7 +83,7 @@
 )

 test('.getRecentHeadlines successfully returns all headline when the
-  number of headlines requested is undefined', (done)->
+ number of headlines requested is undefined', (done)->
   indicatorData = [
     {
       "year": 1999,
@@ -182,7 +182,7 @@
 )

 test('.calculateRecencyOfHeadline when given an indicator with a headline date
-older than the most recent data returns "Newer data available"', (done) ->
+ older than the most recent data returns "Newer data available"', (done) ->
   indicator = new Indicator()
   headlineService = new HeadlineService(indicator)

@@ -206,7 +206,7 @@
 )

 test('.calculateRecencyOfHeadline when given an indicator with a headline date
-equal to or newer than the most recent data returns "Up to date"', (done) ->
+ equal to or newer than the most recent data returns "Up to date"', (done) ->
   indicator = new Indicator()
   headlineService = new HeadlineService(indicator)

@@ -230,7 +230,7 @@
 )

 test('.calculateRecencyOfHeadline when given an indicator with no data
-returns "No Data"', (done) ->
+ returns "No Data"', (done) ->
   indicator = new Indicator()
   headlineService = new HeadlineService(indicator)

@@ -248,7 +248,7 @@
 )

 test('.calculateRecencyOfHeadline when given a headline with
-no periodEnd returns "Newer data available"', (done) ->
+ no periodEnd returns "Newer data available"', (done) ->
   indicator = new Indicator()

   headlineService = new HeadlineService(indicator)
@@ -284,8 +284,8 @@
 )

 test(".parseDateInHeadlines on an indicator with xAxis 'date' (which is an integer),
-and no period specified, when given an integer date headline row,
-adds a 'periodEnd' attribute with the date one year in after the 'date' value", ->
+ and no period specified, when given an integer date headline row,
+ adds a 'periodEnd' attribute with the date one year in after the 'date' value", ->
   indicator = new Indicator(
     indicatorDefinition:
       xAxis: "date",
@@ -326,7 +326,7 @@
 )

 test(".parseDateInHeadlines on an indicator where the frequency is 'quarterly'
-sets periodEnd to 3 months after the initial 'date'", ->
+ sets periodEnd to 3 months after the initial 'date'", ->

   indicator = new Indicator(
     indicatorDefinition:
@@ -351,7 +351,7 @@
 )

 test("#populateNarrativeRecencyOfIndicators populates the narrative recency attribute for
-the given indicators", (done)->
+ the given indicators", (done)->
   indicator = new Indicator()
   indicators = [indicator]

@@ -378,11 +378,11 @@
 )

 test("#narrativeRecencyTextIsUpToDate given text which is in the list of up to
-date statuses returns true", ->
+ date statuses returns true", ->
   assert.isTrue HeadlineService.narrativeRecencyTextIsUpToDate('Up to date')
 )

 test("#narrativeRecencyTextIsUpToDate given text which is not in the list of up to
-date statuses returns false", ->
+ date statuses returns false", ->
   assert.isFalse HeadlineService.narrativeRecencyTextIsUpToDate('Newer data available')
 )


fixed test cases

fixed test cases

--- testApp/app/controllers/layers.coffee
+++ testApp/app/controllers/layers.coffee
@@ -146,11 +146,11 @@

   @testwillchangeEvent: ->
     eventHandler = steroids.layers.on 'willchange', (event) ->
-      targetId = if event.target.webview.id?
+      targetId = if event.target? and event.target.webview.id?
         event.target.webview.id
       else
         ""
-      sourceId = if event.source.webview.id?
+      sourceId = if event.source? and event.source.webview.id?
         event.source.webview.id
       else
         ""
@@ -163,11 +163,11 @@

   @testdidchangeEvent: ->
     eventHandler = steroids.layers.on 'didchange', (event) ->
-      targetId = if event.target.webview.id?
+      targetId = if event.target? and event.target.webview.id?
         event.target.webview.id
       else
         ""
-      sourceId = if event.source.webview.id?
+      sourceId = if event.source? and event.source.webview.id?
         event.source.webview.id
       else
         ""


Ensure window has loaded for intial window width

--- source/assets/javascripts/teleport.coffee
+++ source/assets/javascripts/teleport.coffee
@@ -7,8 +7,9 @@
     size.replace(/\"/g, '')

 class Teleporter
-  lastWidth: Viewport.getWidth()
-  widths: Viewport.widths.reverse()
+  constructor: ->
+    @lastWidth = Viewport.getWidth()
+    @widths = Viewport.widths.reverse()

   teleport: ($source, $target) ->
     return false unless $target and $source


Remove configureTable.

Remove configureTable.

--- app/javascripts/modeling.coffee
+++ app/javascripts/modeling.coffee
@@ -1,137 +1,52 @@
-define ['angular', 'lodash', 'chart'], (ng, _) ->
+define ['angular', 'lodash', 'k-trans', 'v-e', 'tau-i', 'chart'], (ng, _, Ktrans, Ve, TauI) ->
   modeling = ng.module 'qiprofile.modeling', ['qiprofile.chart']

   modeling.factory 'Modeling', ['Chart', (Chart) ->
     # The common modeling x-axis specification.
-    x =
+    X_DATA_SPEC =
       label: 'Visit Date'
-      accessor: (session) -> session.acquisitionDate.valueOf()
+      accessor: (mdlResult) ->
+        mdlResult.session.acquisitionDate.valueOf()

-    # The chart-specific y-axis specifications.
-    #
-    # TODO - support multiple modeling by replacing the session
-    #  arguments below with a modeling result.
-    #
-    y =
-      ktrans:
-        label: 'Ktrans'
-        data:
-          [
-            {
-              label: 'FXL Ktrans'
-              color: 'BurlyWood'
-              accessor: (session) -> session.modeling[0].fxlKTrans.average
-            }
-            {
-              label: 'FXR Ktrans'
-              color: 'OliveDrab'
-              accessor: (session) -> session.modeling[0].fxrKTrans.average
-            }
-          ]
-      ve:
-        label: 'v_e'
-        data:
-          [
-            {
-              label: 'v_e'
-              color: 'MediumSeaGreen'
-              accessor: (session) -> session.modeling[0].vE.average
-            }
-          ]
-      taui:
-        label: 'tau_i'
-        data:
-          [
-            {
-              label: 'tau_i'
-              color: 'PaleVioletRed'
-              accessor: (session) -> session.modeling[0].tauI.average
-            }
-          ]
-
-    # The chart data access specifications.
-    DATA_SPECS =
-      ktrans: {x: x, y: y.ktrans}
-      ve: {x: x, y: y.ve}
-      taui: {x: x, y: y.taui}
-
     # The PK modeling paramater properties, including the delta Ktrans.
     PK_PARAMS: ['fxlKTrans', 'fxrKTrans', 'deltaKTrans', 'vE', 'tauI']
-
-    # @param sessions the session array
-    # @param chart the chart name
+
+    # Configures the d3 chart with the given format. The format is an
+    # object in the form {label: string, data: array}
+    # where the data array has one object per data series in the form
+    # {label: string, color: color, accessor: (modelingResult) -> body}
+    #
+    # @param modelingResults the session modeling results array
+    # @param dataSeriesSpec the chart y-axis {label, data} format specification
     # @returns the nvd3 chart dataSpec
-    configureChart: (sessions, chart) ->
+    configureChart: (modelingResults, dataSeriesSpec) ->
       # @returns the nvd3 tooltip HTML
       tooltip = (key, x, y, e, graph) ->
         "<b>#{ key }</b>: #{ y }"
-
-      # The nvd3 data configuration.
-      dataSpec = DATA_SPECS[chart]
+
+      # The session date x values.
+      xValues = (X_DATA_SPEC.accessor(mdlResult) for mdlResult in modelingResults)
+
+      # The chart data specification.
+      spec =
+        x: X_DATA_SPEC
+        y: dataSeriesSpec
+
       # Return the standard chart configuration extended
       # with the following:
       # * the xValues and xFormat properties
       # * the tooltip function
-      _.extend Chart.configureChart(sessions, dataSpec),
-        xValues: (dataSpec.x.accessor(sess) for sess in sessions)
+      _.extend Chart.configureChart(modelingResults, spec),
+        xValues: xValues
         xFormat: Chart.dateFormat
         tooltip: tooltip

-    # Configures the modeling tables.
-    configureTable: (sessions) ->
-      sessionsWithChangeProperties = (sessions) ->
-        # @param current the current modeling parameters
-        # @param previous the previous modeling parameters
-        # @returns the session objects extended to include
-        #   the percent change properties for all but the
-        #   first session
-        addSessionChangeProperties = (current, previous) ->
-          # @param current the current modeling parameters
-          # @param previous the previous modeling parameters
-          # @returns the percent change properties object
-          extension = (current, previous) ->
-            # @param current the current value
-            # @param previous the previous value
-            # @returns the percent change
-            percentChange = (current, previous) ->
-              (current - previous)/previous * 100
-
-            # Return an object with the change properties.
-            deltaKTransPctChange: percentChange(current.deltaKTrans.average, previous.deltaKTrans.average)
-            fxlKTransPctChange: percentChange(current.fxlKTrans.average, previous.fxlKTrans.average)
-            fxrKTransPctChange: percentChange(current.fxrKTrans.average, previous.fxrKTrans.average)
-            vEPctChange: percentChange(current.vE.average, previous.vE.average)
-            tauIPctChange: percentChange(current.tauI.average, previous.tauI.average)
-
-          # If this is not the first session's modeling object,
-          # then extend the object with the percent change properties,
-          # otherwise, return the first modeling object unchanged.
-          if previous
-            _.extend current, extension(current, previous)
-          else
-            current
+    kTrans:
+      dataSeriesConfig: Ktrans.CHART_DATA_SERIES_CONFIG

-        # The previous modeling object.
-        prev = null
-        # The modeling objects extended with change properties.
-        result = []
-        # Extend all but the first modeling object with change properties.
-        #
-        # TODO - support multiple modeling by iterating over the modeling
-        # results, then the sessions in the loop below.
-        #
-        for sess in sessions
-          curr = sess.modeling[0]
-          if curr
-            result.push addSessionChangeProperties(curr, prev)
-            prev = curr
-        # Return the result.
-        result
+    vE:
+      dataSeriesConfig: Ve.CHART_DATA_SERIES_CONFIG

-      # Return the configuration object.
-      data: sessionsWithChangeProperties(sessions)
-      # The accordian controls.
-      ktransOpen: true
-      veOpen: true
-      tauiOpen: true
+    tauI:
+      dataSeriesConfig: TauI.CHART_DATA_SERIES_CONFIG
   ]


update

update

--- app/templates/_gruntfile.coffee
+++ app/templates/_gruntfile.coffee
@@ -80,8 +80,8 @@

     nodemon:
       dev:
+        script: 'server.js'
         options:
-          file: 'server.js'
           args: []
           ignoredFiles: ['public/**']
           watchedExtensions: ['js']
@@ -89,7 +89,7 @@
           delayTime: 1
           env:
               PORT: 3000
-          cwd: __dirname
+          cwd: "#{__dirname}/app/dist/server"

     concurrent: